OSDN Git Service

Merge change 24110 into eclair
[android-x86/dalvik.git] / vm / CheckJni.c
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /*
18  * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
19  *
20  * We want to verify types, make sure class and field IDs are valid, and
21  * ensure that JNI's semantic expectations are being met.  JNI seems to
22  * be relatively lax when it comes to requirements for permission checks,
23  * e.g. access to private methods is generally allowed from anywhere.
24  *
25  * TODO: keep a counter on global Get/Release.  Report a warning if some Gets
26  * were not Released.  Do not count explicit Add/DeleteGlobalRef calls (or
27  * count them separately, so we can complain if they exceed a certain
28  * threshold).
29  *
30  * TODO: verify that the methodID passed into the Call functions is for
31  * a method in the specified class.
32  */
33 #include "Dalvik.h"
34 #include "JniInternal.h"
35
36 #include <zlib.h>
37
38 static void abortMaybe(void);       // fwd
39
40
41 /*
42  * ===========================================================================
43  *      JNI call bridge wrapper
44  * ===========================================================================
45  */
46
47 /*
48  * Check the result of a native method call that returns an object reference.
49  *
50  * The primary goal here is to verify that native code is returning the
51  * correct type of object.  If it's declared to return a String but actually
52  * returns a byte array, things will fail in strange ways later on.
53  *
54  * This can be a fairly expensive operation, since we have to look up the
55  * return type class by name in method->clazz' class loader.  We take a
56  * shortcut here and allow the call to succeed if the descriptor strings
57  * match.  This will allow some false-positives when a class is redefined
58  * by a class loader, but that's rare enough that it doesn't seem worth
59  * testing for.
60  *
61  * At this point, pResult->l has already been converted to an object pointer.
62  */
63 static void checkCallCommon(const u4* args, JValue* pResult,
64     const Method* method, Thread* self)
65 {
66     assert(pResult->l != NULL);
67     Object* resultObj = (Object*) pResult->l;
68     ClassObject* objClazz = resultObj->clazz;
69
70     /*
71      * Make sure that pResult->l is an instance of the type this
72      * method was expected to return.
73      */
74     const char* declType = dexProtoGetReturnType(&method->prototype);
75     const char* objType = objClazz->descriptor;
76     if (strcmp(declType, objType) == 0) {
77         /* names match; ignore class loader issues and allow it */
78         LOGV("Check %s.%s: %s io %s (FAST-OK)\n",
79             method->clazz->descriptor, method->name, objType, declType);
80     } else {
81         /*
82          * Names didn't match.  We need to resolve declType in the context
83          * of method->clazz->classLoader, and compare the class objects
84          * for equality.
85          *
86          * Since we're returning an instance of declType, it's safe to
87          * assume that it has been loaded and initialized (or, for the case
88          * of an array, generated), so we can just look for it in the
89          * loaded-classes list.
90          */
91         ClassObject* declClazz;
92
93         declClazz = dvmLookupClass(declType, method->clazz->classLoader, false);
94         if (declClazz == NULL) {
95             LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
96                 declType, objType);
97             LOGW("             failed in %s.%s ('%s' not found)\n",
98                 method->clazz->descriptor, method->name, declType);
99             abortMaybe();
100             return;
101         }
102         if (!dvmInstanceof(objClazz, declClazz)) {
103             LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
104                 declType, objType);
105             LOGW("             failed in %s.%s\n",
106                 method->clazz->descriptor, method->name);
107             abortMaybe();
108             return;
109         } else {
110             LOGV("Check %s.%s: %s io %s (SLOW-OK)\n",
111                 method->clazz->descriptor, method->name, objType, declType);
112         }
113     }
114 }
115
116 /*
117  * Determine if we need to check the return type coming out of the call.
118  *
119  * (We don't do this at the top of checkCallCommon() because this is on
120  * the critical path for native method calls.)
121  */
122 static inline bool callNeedsCheck(const u4* args, JValue* pResult,
123     const Method* method, Thread* self)
124 {
125     return (method->shorty[0] == 'L' && !dvmCheckException(self) &&
126             pResult->l != NULL);
127 }
128
129 /*
130  * Check a call into native code.
131  */
132 void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
133     const Method* method, Thread* self)
134 {
135     dvmCallJNIMethod_general(args, pResult, method, self);
136     if (callNeedsCheck(args, pResult, method, self))
137         checkCallCommon(args, pResult, method, self);
138 }
139
140 /*
141  * Check a synchronized call into native code.
142  */
143 void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
144     const Method* method, Thread* self)
145 {
146     dvmCallJNIMethod_synchronized(args, pResult, method, self);
147     if (callNeedsCheck(args, pResult, method, self))
148         checkCallCommon(args, pResult, method, self);
149 }
150
151 /*
152  * Check a virtual call with no reference arguments (other than "this").
153  */
154 void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
155     const Method* method, Thread* self)
156 {
157     dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
158     if (callNeedsCheck(args, pResult, method, self))
159         checkCallCommon(args, pResult, method, self);
160 }
161
162 /*
163  * Check a static call with no reference arguments (other than "clazz").
164  */
165 void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
166     const Method* method, Thread* self)
167 {
168     dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
169     if (callNeedsCheck(args, pResult, method, self))
170         checkCallCommon(args, pResult, method, self);
171 }
172
173
174 /*
175  * ===========================================================================
176  *      JNI function helpers
177  * ===========================================================================
178  */
179
180 #define JNI_ENTER()     dvmChangeStatus(NULL, THREAD_RUNNING)
181 #define JNI_EXIT()      dvmChangeStatus(NULL, THREAD_NATIVE)
182
183 #define BASE_ENV(_env)  (((JNIEnvExt*)_env)->baseFuncTable)
184 #define BASE_VM(_vm)    (((JavaVMExt*)_vm)->baseFuncTable)
185
186 #define kRedundantDirectBufferTest false
187
188 /*
189  * Flags passed into checkThread().
190  */
191 #define kFlag_Default       0x0000
192
193 #define kFlag_CritBad       0x0000      /* calling while in critical is bad */
194 #define kFlag_CritOkay      0x0001      /* ...okay */
195 #define kFlag_CritGet       0x0002      /* this is a critical "get" */
196 #define kFlag_CritRelease   0x0003      /* this is a critical "release" */
197 #define kFlag_CritMask      0x0003      /* bit mask to get "crit" value */
198
199 #define kFlag_ExcepBad      0x0000      /* raised exceptions are bad */
200 #define kFlag_ExcepOkay     0x0004      /* ...okay */
201
202 /*
203  * Enter/exit macros for JNI env "check" functions.  These do not change
204  * the thread state within the VM.
205  */
206 #define CHECK_ENTER(_env, _flags)                                           \
207     do {                                                                    \
208         JNI_TRACE(true, true);                                              \
209         checkThread(_env, _flags, __FUNCTION__);                            \
210     } while(false)
211
212 #define CHECK_EXIT(_env)                                                    \
213     do { JNI_TRACE(false, true); } while(false)
214
215
216 /*
217  * Enter/exit macros for JNI invocation interface "check" functions.  These
218  * do not change the thread state within the VM.
219  *
220  * Set "_hasmeth" to true if we have a valid thread with a method pointer.
221  * We won't have one before attaching a thread, after detaching a thread, or
222  * after destroying the VM.
223  */
224 #define CHECK_VMENTER(_vm, _hasmeth)                                        \
225     do { JNI_TRACE(true, _hasmeth); } while(false)
226 #define CHECK_VMEXIT(_vm, _hasmeth)                                         \
227     do { JNI_TRACE(false, _hasmeth); } while(false)
228
229 #define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic)            \
230     checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
231 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid)                           \
232     checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
233 #define CHECK_CLASS(_env, _clazz)                                           \
234     checkClass(_env, _clazz, __FUNCTION__)
235 #define CHECK_STRING(_env, _str)                                            \
236     checkString(_env, _str, __FUNCTION__)
237 #define CHECK_UTF_STRING(_env, _str, _nullok)                               \
238     checkUtfString(_env, _str, _nullok, __FUNCTION__)
239 #define CHECK_CLASS_NAME(_env, _str)                                        \
240     checkClassName(_env, _str, __FUNCTION__)
241 #define CHECK_OBJECT(_env, _obj)                                            \
242     checkObject(_env, _obj, __FUNCTION__)
243 #define CHECK_ARRAY(_env, _array)                                           \
244     checkArray(_env, _array, __FUNCTION__)
245 #define CHECK_RELEASE_MODE(_env, _mode)                                     \
246     checkReleaseMode(_env, _mode, __FUNCTION__)
247 #define CHECK_LENGTH_POSITIVE(_env, _length)                                \
248     checkLengthPositive(_env, _length, __FUNCTION__)
249 #define CHECK_NON_NULL(_env, _ptr)                                          \
250     checkNonNull(_env, _ptr, __FUNCTION__)
251
252 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic)                       \
253     checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
254
255 /*
256  * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
257  */
258 #define JNI_TRACE(_entry, _hasmeth)                                         \
259     do {                                                                    \
260         if (gDvm.verboseJni && (_entry)) {                                  \
261             static const char* classDescriptor = "???";                     \
262             static const char* methodName = "???";                          \
263             if (_hasmeth) {                                                 \
264                 const Method* meth = dvmGetCurrentJNIMethod();              \
265                 classDescriptor = meth->clazz->descriptor;                  \
266                 methodName = meth->name;                                    \
267             }                                                               \
268             /* use +6 to drop the leading "Check_" */                       \
269             LOGI("JNI: %s (from %s.%s)",                                    \
270                 (__FUNCTION__)+6, classDescriptor, methodName);             \
271         }                                                                   \
272     } while(false)
273
274 /*
275  * Log the current location.
276  *
277  * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
278  */
279 static void showLocation(const Method* meth, const char* func)
280 {
281     char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
282     LOGW("             in %s.%s %s (%s)\n",
283         meth->clazz->descriptor, meth->name, desc, func + 6);
284     free(desc);
285 }
286
287 /*
288  * Abort if we are configured to bail out on JNI warnings.
289  */
290 static void abortMaybe(void)
291 {
292     JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
293     if (vm->warnError) {
294         dvmDumpThread(dvmThreadSelf(), false);
295         dvmAbort();
296     }
297 }
298
299 /*
300  * Verify that the current thread is (a) attached and (b) associated with
301  * this particular instance of JNIEnv.
302  *
303  * Verify that, if this thread previously made a critical "get" call, we
304  * do the corresponding "release" call before we try anything else.
305  *
306  * Verify that, if an exception has been raised, the native code doesn't
307  * make any JNI calls other than the Exception* methods.
308  *
309  * TODO? if we add support for non-JNI native calls, make sure that the
310  * method at the top of the interpreted stack is a JNI method call.  (Or
311  * set a flag in the Thread/JNIEnv when the call is made and clear it on
312  * return?)
313  *
314  * NOTE: we are still in THREAD_NATIVE mode.  A GC could happen at any time.
315  */
316 static void checkThread(JNIEnv* env, int flags, const char* func)
317 {
318     JNIEnvExt* threadEnv;
319     bool printWarn = false;
320     bool printException = false;
321
322     /* get the *correct* JNIEnv by going through our TLS pointer */
323     threadEnv = dvmGetJNIEnvForThread();
324
325     /*
326      * Verify that the JNIEnv we've been handed matches what we expected
327      * to receive.
328      */
329     if (threadEnv == NULL) {
330         LOGE("JNI ERROR: non-VM thread making JNI calls\n");
331         // don't set printWarn -- it'll try to call showLocation()
332         dvmAbort();
333     } else if ((JNIEnvExt*) env != threadEnv) {
334         if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
335             LOGE("JNI: threadEnv != thread->env?\n");
336             dvmAbort();
337         }
338
339         LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
340             threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
341         printWarn = true;
342
343         /* this is a bad idea -- need to throw as we exit, or abort func */
344         //dvmThrowException("Ljava/lang/RuntimeException;",
345         //    "invalid use of JNI env ptr");
346     } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
347         /* correct JNIEnv*; make sure the "self" pointer is correct */
348         LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)\n",
349             ((JNIEnvExt*) env)->self, dvmThreadSelf());
350         dvmAbort();
351     }
352
353     /*
354      * Check for critical resource misuse.
355      */
356     switch (flags & kFlag_CritMask) {
357     case kFlag_CritOkay:    // okay to call this method
358         break;
359     case kFlag_CritBad:     // not okay to call
360         if (threadEnv->critical) {
361             LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
362                 threadEnv->envThreadId);
363             printWarn = true;
364         }
365         break;
366     case kFlag_CritGet:     // this is a "get" call
367         /* don't check here; we allow nested gets */
368         threadEnv->critical++;
369         break;
370     case kFlag_CritRelease: // this is a "release" call
371         threadEnv->critical--;
372         if (threadEnv->critical < 0) {
373             LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
374                 threadEnv->envThreadId);
375             printWarn = true;
376         }
377         break;
378     default:
379         assert(false);
380     }
381
382     /*
383      * Check for raised exceptions.
384      */
385     if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
386         LOGW("JNI WARNING: JNI method called with exception raised\n");
387         printWarn = true;
388         printException = true;
389     }
390
391     if (printWarn)
392         showLocation(dvmGetCurrentJNIMethod(), func);
393     if (printException) {
394         LOGW("Pending exception is:\n");
395         dvmLogExceptionStackTrace();
396     }
397     if (printWarn)
398         abortMaybe();
399 }
400
401 /*
402  * Verify that the field is of the appropriate type.  If the field has an
403  * object type, "obj" is the object we're trying to assign into it.
404  *
405  * Works for both static and instance fields.
406  */
407 static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
408     PrimitiveType prim, bool isStatic, const char* func)
409 {
410     static const char* primNameList[] = {
411         "Object/Array", "boolean", "char", "float", "double",
412         "byte", "short", "int", "long", "void"
413     };
414     const char** primNames = &primNameList[1];      // shift up for PRIM_NOT
415     Field* field = (Field*) fieldID;
416     bool printWarn = false;
417
418     if (fieldID == NULL) {
419         LOGE("JNI ERROR: null field ID\n");
420         abortMaybe();
421     }
422
423     if (field->signature[0] == 'L' || field->signature[0] == '[') {
424         Object* obj = dvmDecodeIndirectRef(env, jobj);
425         if (obj != NULL) {
426             ClassObject* fieldClass =
427                 dvmFindLoadedClass(field->signature);
428             ClassObject* objClass = obj->clazz;
429
430             assert(fieldClass != NULL);
431             assert(objClass != NULL);
432
433             if (!dvmInstanceof(objClass, fieldClass)) {
434                 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
435                     field->name, field->signature, objClass->descriptor);
436                 printWarn = true;
437             }
438         }
439     } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
440         LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
441             field->name, field->signature, primNames[prim]);
442         printWarn = true;
443     } else if (isStatic && !dvmIsStaticField(field)) {
444         if (isStatic)
445             LOGW("JNI WARNING: accessing non-static field %s as static\n",
446                 field->name);
447         else
448             LOGW("JNI WARNING: accessing static field %s as non-static\n",
449                 field->name);
450         printWarn = true;
451     }
452
453     if (printWarn) {
454         showLocation(dvmGetCurrentJNIMethod(), func);
455         abortMaybe();
456     }
457 }
458
459 /*
460  * Verify that "jobj" is a valid object, and that it's an object that JNI
461  * is allowed to know about.  We allow NULL references.
462  *
463  * Switches to "running" mode before performing checks.
464  */
465 static void checkObject(JNIEnv* env, jobject jobj, const char* func)
466 {
467     UNUSED_PARAMETER(env);
468     bool printWarn = false;
469
470     if (jobj == NULL)
471         return;
472
473     JNI_ENTER();
474
475     if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
476         LOGW("JNI WARNING: %p is not a valid JNI reference\n", jobj);
477         printWarn = true;
478     } else {
479         Object* obj = dvmDecodeIndirectRef(env, jobj);
480
481         if (obj == NULL || !dvmIsValidObject(obj)) {
482             LOGW("JNI WARNING: native code passing in bad object %p %p (%s)\n",
483                 jobj, obj, func);
484             printWarn = true;
485         }
486     }
487
488     if (printWarn) {
489         showLocation(dvmGetCurrentJNIMethod(), func);
490         abortMaybe();
491     }
492
493     JNI_EXIT();
494 }
495
496 /*
497  * Verify that "clazz" actually points to a class object.  (Also performs
498  * checkObject.)
499  *
500  * We probably don't need to identify where we're being called from,
501  * because the VM is most likely about to crash and leave a core dump
502  * if something is wrong.
503  *
504  * Because we're looking at an object on the GC heap, we have to switch
505  * to "running" mode before doing the checks.
506  */
507 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
508 {
509     JNI_ENTER();
510     bool printWarn = false;
511
512     ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
513
514     if (clazz == NULL) {
515         LOGW("JNI WARNING: received null jclass\n");
516         printWarn = true;
517     } else if (!dvmIsValidObject((Object*) clazz)) {
518         LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
519         printWarn = true;
520     } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
521         LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
522             jclazz, clazz->descriptor);
523         printWarn = true;
524     }
525     JNI_EXIT();
526
527     if (printWarn)
528         abortMaybe();
529     else
530         checkObject(env, jclazz, func);
531 }
532
533 /*
534  * Verify that "str" is non-NULL and points to a String object.
535  *
536  * Since we're dealing with objects, switch to "running" mode.
537  */
538 static void checkString(JNIEnv* env, jstring jstr, const char* func)
539 {
540     JNI_ENTER();
541     bool printWarn = false;
542
543     Object* obj = dvmDecodeIndirectRef(env, jstr);
544
545     if (obj == NULL) {
546         LOGW("JNI WARNING: received null jstring (%s)\n", func);
547         printWarn = true;
548     } else if (obj->clazz != gDvm.classJavaLangString) {
549         /*
550          * TODO: we probably should test dvmIsValidObject first, because
551          * this will crash if "obj" is non-null but pointing to an invalid
552          * memory region.  However, the "is valid" test is a little slow,
553          * we're doing it again over in checkObject().
554          */
555         if (dvmIsValidObject(obj))
556             LOGW("JNI WARNING: jstring %p points to non-string object (%s)\n",
557                 jstr, func);
558         else
559             LOGW("JNI WARNING: jstring %p is bogus (%s)\n", jstr, func);
560         printWarn = true;
561     }
562     JNI_EXIT();
563
564     if (printWarn)
565         abortMaybe();
566     else
567         checkObject(env, jstr, func);
568 }
569
570 /*
571  * Verify that "bytes" points to valid "modified UTF-8" data.
572  */
573 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
574     const char* func)
575 {
576     const char* origBytes = bytes;
577
578     if (bytes == NULL) {
579         if (!nullOk) {
580             LOGW("JNI WARNING: unexpectedly null UTF string\n");
581             goto fail;
582         }
583
584         return;
585     }
586
587     while (*bytes != '\0') {
588         u1 utf8 = *(bytes++);
589         // Switch on the high four bits.
590         switch (utf8 >> 4) {
591             case 0x00:
592             case 0x01:
593             case 0x02:
594             case 0x03:
595             case 0x04:
596             case 0x05:
597             case 0x06:
598             case 0x07: {
599                 // Bit pattern 0xxx. No need for any extra bytes.
600                 break;
601             }
602             case 0x08:
603             case 0x09:
604             case 0x0a:
605             case 0x0b:
606             case 0x0f: {
607                 /*
608                  * Bit pattern 10xx or 1111, which are illegal start bytes.
609                  * Note: 1111 is valid for normal UTF-8, but not the
610                  * modified UTF-8 used here.
611                  */
612                 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
613                 goto fail;
614             }
615             case 0x0e: {
616                 // Bit pattern 1110, so there are two additional bytes.
617                 utf8 = *(bytes++);
618                 if ((utf8 & 0xc0) != 0x80) {
619                     LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
620                     goto fail;
621                 }
622                 // Fall through to take care of the final byte.
623             }
624             case 0x0c:
625             case 0x0d: {
626                 // Bit pattern 110x, so there is one additional byte.
627                 utf8 = *(bytes++);
628                 if ((utf8 & 0xc0) != 0x80) {
629                     LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
630                     goto fail;
631                 }
632                 break;
633             }
634         }
635     }
636
637     return;
638
639 fail:
640     LOGW("             string: '%s'\n", origBytes);
641     showLocation(dvmGetCurrentJNIMethod(), func);
642     abortMaybe();
643 }
644
645 /*
646  * In some circumstances the VM will screen class names, but it doesn't
647  * for class lookup.  When things get bounced through a class loader, they
648  * can actually get normalized a couple of times; as a result, passing in
649  * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
650  * work in some circumstances.
651  *
652  * This is incorrect and could cause strange behavior or compatibility
653  * problems, so we want to screen that out here.
654  *
655  * We expect "full-qualified" class names, like "java/lang/Thread" or
656  * "[Ljava/lang/Object;".
657  */
658 static void checkClassName(JNIEnv* env, const char* className, const char* func)
659 {
660     const char* cp;
661
662     /* quick check for illegal chars */
663     cp = className;
664     while (*cp != '\0') {
665         if (*cp == '.')
666             goto fail;
667         cp++;
668     }
669
670     // TODO: need a more rigorous check here
671
672     return;
673
674 fail:
675     LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
676     abortMaybe();
677 }
678
679 /*
680  * Verify that "array" is non-NULL and points to an Array object.
681  *
682  * Since we're dealing with objects, switch to "running" mode.
683  */
684 static void checkArray(JNIEnv* env, jarray jarr, const char* func)
685 {
686     JNI_ENTER();
687     bool printWarn = false;
688
689     Object* obj = dvmDecodeIndirectRef(env, jarr);
690
691     if (obj == NULL) {
692         LOGW("JNI WARNING: received null array (%s)\n", func);
693         printWarn = true;
694     } else if (obj->clazz->descriptor[0] != '[') {
695         if (dvmIsValidObject(obj))
696             LOGW("JNI WARNING: jarray %p points to non-array object (%s)\n",
697                 jarr, obj->clazz->descriptor);
698         else
699             LOGW("JNI WARNING: jarray %p is bogus\n", jarr);
700         printWarn = true;
701     }
702
703     JNI_EXIT();
704
705     if (printWarn)
706         abortMaybe();
707     else
708         checkObject(env, jarr, func);
709 }
710
711 /*
712  * Verify that the "mode" argument passed to a primitive array Release
713  * function is one of the valid values.
714  */
715 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
716 {
717     if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
718         LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
719         abortMaybe();
720     }
721 }
722
723 /*
724  * Verify that the length argument to array-creation calls is >= 0.
725  */
726 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
727 {
728     if (length < 0) {
729         LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
730         abortMaybe();
731     }
732 }
733
734 /*
735  * Verify that the pointer value is non-NULL.
736  */
737 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
738 {
739     if (ptr == NULL) {
740         LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
741         abortMaybe();
742     }
743 }
744
745 /*
746  * Verify that the method's return type matches the type of call.
747  *
748  * "expectedSigByte" will be 'L' for all objects, including arrays.
749  */
750 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
751     bool isStatic, const char* func)
752 {
753     const Method* meth = (const Method*) methodID;
754     bool printWarn = false;
755
756     if (expectedSigByte != meth->shorty[0]) {
757         LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
758         printWarn = true;
759     } else if (isStatic && !dvmIsStaticMethod(meth)) {
760         if (isStatic)
761             LOGW("JNI WARNING: calling non-static method with static call\n");
762         else
763             LOGW("JNI WARNING: calling static method with non-static call\n");
764         printWarn = true;
765     }
766
767     if (printWarn) {
768         char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
769         LOGW("             calling %s.%s %s\n",
770             meth->clazz->descriptor, meth->name, desc);
771         free(desc);
772         showLocation(dvmGetCurrentJNIMethod(), func);
773         abortMaybe();
774     }
775 }
776
777 /*
778  * Verify that this static field ID is valid for this class.
779  */
780 static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
781 {
782     ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
783     StaticField* base = clazz->sfields;
784     int fieldCount = clazz->sfieldCount;
785
786     if ((StaticField*) fieldID < base ||
787         (StaticField*) fieldID >= base + fieldCount)
788     {
789         LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
790             fieldID, clazz->descriptor);
791         LOGW("             base=%p count=%d\n", base, fieldCount);
792         abortMaybe();
793     }
794 }
795
796 /*
797  * Verify that this instance field ID is valid for this object.
798  */
799 static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
800     const char* func)
801 {
802     JNI_ENTER();
803
804     if (jobj == NULL) {
805         LOGW("JNI WARNING: invalid null object (%s)\n", func);
806         abortMaybe();
807         goto bail;
808     }
809
810     Object* obj = dvmDecodeIndirectRef(env, jobj);
811     ClassObject* clazz = obj->clazz;
812
813     /*
814      * Check this class and all of its superclasses for a matching field.
815      * Don't need to scan interfaces.
816      */
817     while (clazz != NULL) {
818         if ((InstField*) fieldID >= clazz->ifields &&
819             (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
820         {
821             goto bail;
822         }
823
824         clazz = clazz->super;
825     }
826
827     LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
828         fieldID, obj->clazz->descriptor);
829     abortMaybe();
830
831 bail:
832     JNI_EXIT();
833 }
834
835
836 /*
837  * ===========================================================================
838  *      Guarded arrays
839  * ===========================================================================
840  */
841
842 #define kGuardLen       512         /* must be multiple of 2 */
843 #define kGuardPattern   0xd5e3      /* uncommon values; d5e3d5e3 invalid addr */
844 #define kGuardMagic     0xffd5aa96
845 #define kGuardExtra     sizeof(GuardExtra)
846
847 /* this gets tucked in at the start of the buffer; struct size must be even */
848 typedef struct GuardExtra {
849     u4          magic;
850     uLong       adler;
851     size_t      originalLen;
852     const void* originalPtr;
853 } GuardExtra;
854
855 /* find the GuardExtra given the pointer into the "live" data */
856 inline static GuardExtra* getGuardExtra(const void* dataBuf)
857 {
858     u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
859     return (GuardExtra*) fullBuf;
860 }
861
862 /*
863  * Create an oversized buffer to hold the contents of "buf".  Copy it in,
864  * filling in the area around it with guard data.
865  *
866  * We use a 16-bit pattern to make a rogue memset less likely to elude us.
867  */
868 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
869 {
870     GuardExtra* pExtra;
871     size_t newLen = (len + kGuardLen +1) & ~0x01;
872     u1* newBuf;
873     u2* pat;
874     int i;
875
876     newBuf = (u1*)malloc(newLen);
877     if (newBuf == NULL) {
878         LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
879         dvmAbort();
880     }
881
882     /* fill it in with a pattern */
883     pat = (u2*) newBuf;
884     for (i = 0; i < (int)newLen / 2; i++)
885         *pat++ = kGuardPattern;
886
887     /* copy the data in; note "len" could be zero */
888     memcpy(newBuf + kGuardLen / 2, buf, len);
889
890     /* if modification is not expected, grab a checksum */
891     uLong adler = 0;
892     if (!modOkay) {
893         adler = adler32(0L, Z_NULL, 0);
894         adler = adler32(adler, buf, len);
895         *(uLong*)newBuf = adler;
896     }
897
898     pExtra = (GuardExtra*) newBuf;
899     pExtra->magic = kGuardMagic;
900     pExtra->adler = adler;
901     pExtra->originalPtr = buf;
902     pExtra->originalLen = len;
903
904     return newBuf + kGuardLen / 2;
905 }
906
907 /*
908  * Verify the guard area and, if "modOkay" is false, that the data itself
909  * has not been altered.
910  *
911  * The caller has already checked that "dataBuf" is non-NULL.
912  */
913 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
914 {
915     static const u4 kMagicCmp = kGuardMagic;
916     const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
917     const GuardExtra* pExtra = getGuardExtra(dataBuf);
918     size_t len;
919     const u2* pat;
920     int i;
921
922     /*
923      * Before we do anything with "pExtra", check the magic number.  We
924      * do the check with memcmp rather than "==" in case the pointer is
925      * unaligned.  If it points to completely bogus memory we're going
926      * to crash, but there's no easy way around that.
927      */
928     if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
929         u1 buf[4];
930         memcpy(buf, &pExtra->magic, 4);
931         LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
932              "-- incorrect data pointer %p?\n",
933             buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
934         return false;
935     }
936
937     len = pExtra->originalLen;
938
939     /* check bottom half of guard; skip over optional checksum storage */
940     pat = (u2*) fullBuf;
941     for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
942     {
943         if (pat[i] != kGuardPattern) {
944             LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
945                 fullBuf, i*2);
946             return false;
947         }
948     }
949
950     int offset = kGuardLen / 2 + len;
951     if (offset & 0x01) {
952         /* odd byte; expected value depends on endian-ness of host */
953         const u2 patSample = kGuardPattern;
954         if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
955             LOGE("JNI: guard pattern disturbed in odd byte after %p "
956                  "(+%d) 0x%02x 0x%02x\n",
957                 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
958             return false;
959         }
960         offset++;
961     }
962
963     /* check top half of guard */
964     pat = (u2*) (fullBuf + offset);
965     for (i = 0; i < kGuardLen / 4; i++) {
966         if (pat[i] != kGuardPattern) {
967             LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
968                 fullBuf, offset + i*2);
969             return false;
970         }
971     }
972
973     /*
974      * If modification is not expected, verify checksum.  Strictly speaking
975      * this is wrong: if we told the client that we made a copy, there's no
976      * reason they can't alter the buffer.
977      */
978     if (!modOkay) {
979         uLong adler = adler32(0L, Z_NULL, 0);
980         adler = adler32(adler, dataBuf, len);
981         if (pExtra->adler != adler) {
982             LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
983                 pExtra->adler, adler, dataBuf);
984             return false;
985         }
986     }
987
988     return true;
989 }
990
991 /*
992  * Free up the guard buffer, scrub it, and return the original pointer.
993  */
994 static void* freeGuardedCopy(void* dataBuf)
995 {
996     u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
997     const GuardExtra* pExtra = getGuardExtra(dataBuf);
998     void* originalPtr = (void*) pExtra->originalPtr;
999     size_t len = pExtra->originalLen;
1000
1001     memset(dataBuf, 0xdd, len);
1002     free(fullBuf);
1003     return originalPtr;
1004 }
1005
1006 /*
1007  * Just pull out the original pointer.
1008  */
1009 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
1010 {
1011     const GuardExtra* pExtra = getGuardExtra(dataBuf);
1012     return (void*) pExtra->originalPtr;
1013 }
1014
1015 /*
1016  * Grab the data length.
1017  */
1018 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
1019 {
1020     const GuardExtra* pExtra = getGuardExtra(dataBuf);
1021     return pExtra->originalLen;
1022 }
1023
1024 /*
1025  * Return the width, in bytes, of a primitive type.
1026  */
1027 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
1028 {
1029     static const int lengths[PRIM_MAX] = {
1030         1,      // boolean
1031         2,      // char
1032         4,      // float
1033         8,      // double
1034         1,      // byte
1035         2,      // short
1036         4,      // int
1037         8,      // long
1038         -1,     // void
1039     };
1040     assert(primType >= 0 && primType < PRIM_MAX);
1041     return lengths[primType];
1042 }
1043
1044 /*
1045  * Create a guarded copy of a primitive array.  Modifications to the copied
1046  * data are allowed.  Returns a pointer to the copied data.
1047  */
1048 static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
1049     jboolean* isCopy)
1050 {
1051     ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1052     PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1053     int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1054     void* result;
1055
1056     result = createGuardedCopy(arrObj->contents, len, true);
1057
1058     if (isCopy != NULL)
1059         *isCopy = JNI_TRUE;
1060
1061     return result;
1062 }
1063
1064 /*
1065  * Perform the array "release" operation, which may or may not copy data
1066  * back into the VM, and may or may not release the underlying storage.
1067  */
1068 static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
1069     int mode)
1070 {
1071     ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1072     PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1073     //int len = array->length * dvmPrimitiveTypeWidth(primType);
1074     bool release, copyBack;
1075     u1* result;
1076
1077     if (!checkGuardedCopy(dataBuf, true)) {
1078         LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
1079         abortMaybe();
1080         return NULL;
1081     }
1082
1083     switch (mode) {
1084     case 0:
1085         release = copyBack = true;
1086         break;
1087     case JNI_ABORT:
1088         release = true;
1089         copyBack = false;
1090         break;
1091     case JNI_COMMIT:
1092         release = false;
1093         copyBack = true;
1094         break;
1095     default:
1096         LOGE("JNI: bad release mode %d\n", mode);
1097         dvmAbort();
1098         return NULL;
1099     }
1100
1101     if (copyBack) {
1102         size_t len = getGuardedCopyOriginalLen(dataBuf);
1103         memcpy(arrObj->contents, dataBuf, len);
1104     }
1105
1106     if (release) {
1107         result = (u1*) freeGuardedCopy(dataBuf);
1108     } else {
1109         result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
1110     }
1111
1112     /* pointer is to the array contents; back up to the array object */
1113     result -= offsetof(ArrayObject, contents);
1114
1115     return result;
1116 }
1117
1118
1119 /*
1120  * ===========================================================================
1121  *      JNI functions
1122  * ===========================================================================
1123  */
1124
1125 static jint Check_GetVersion(JNIEnv* env)
1126 {
1127     CHECK_ENTER(env, kFlag_Default);
1128     jint result;
1129     result = BASE_ENV(env)->GetVersion(env);
1130     CHECK_EXIT(env);
1131     return result;
1132 }
1133
1134 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1135     const jbyte* buf, jsize bufLen)
1136 {
1137     CHECK_ENTER(env, kFlag_Default);
1138     CHECK_OBJECT(env, loader);
1139     CHECK_UTF_STRING(env, name, false);
1140     CHECK_CLASS_NAME(env, name);
1141     jclass result;
1142     result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
1143     CHECK_EXIT(env);
1144     return result;
1145 }
1146
1147 static jclass Check_FindClass(JNIEnv* env, const char* name)
1148 {
1149     CHECK_ENTER(env, kFlag_Default);
1150     CHECK_UTF_STRING(env, name, false);
1151     CHECK_CLASS_NAME(env, name);
1152     jclass result;
1153     result = BASE_ENV(env)->FindClass(env, name);
1154     CHECK_EXIT(env);
1155     return result;
1156 }
1157
1158 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
1159 {
1160     CHECK_ENTER(env, kFlag_Default);
1161     CHECK_CLASS(env, clazz);
1162     jclass result;
1163     result = BASE_ENV(env)->GetSuperclass(env, clazz);
1164     CHECK_EXIT(env);
1165     return result;
1166 }
1167
1168 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1169     jclass clazz2)
1170 {
1171     CHECK_ENTER(env, kFlag_Default);
1172     CHECK_CLASS(env, clazz1);
1173     CHECK_CLASS(env, clazz2);
1174     jboolean result;
1175     result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1176     CHECK_EXIT(env);
1177     return result;
1178 }
1179
1180 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1181 {
1182     CHECK_ENTER(env, kFlag_Default);
1183     CHECK_OBJECT(env, method);
1184     jmethodID result;
1185     result = BASE_ENV(env)->FromReflectedMethod(env, method);
1186     CHECK_EXIT(env);
1187     return result;
1188 }
1189
1190 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1191 {
1192     CHECK_ENTER(env, kFlag_Default);
1193     CHECK_OBJECT(env, field);
1194     jfieldID result;
1195     result = BASE_ENV(env)->FromReflectedField(env, field);
1196     CHECK_EXIT(env);
1197     return result;
1198 }
1199
1200 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1201     jmethodID methodID, jboolean isStatic)
1202 {
1203     CHECK_ENTER(env, kFlag_Default);
1204     CHECK_CLASS(env, cls);
1205     jobject result;
1206     result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1207     CHECK_EXIT(env);
1208     return result;
1209 }
1210
1211 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1212     jboolean isStatic)
1213 {
1214     CHECK_ENTER(env, kFlag_Default);
1215     CHECK_CLASS(env, cls);
1216     jobject result;
1217     result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1218     CHECK_EXIT(env);
1219     return result;
1220 }
1221
1222 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1223 {
1224     CHECK_ENTER(env, kFlag_Default);
1225     CHECK_OBJECT(env, obj);
1226     jint result;
1227     result = BASE_ENV(env)->Throw(env, obj);
1228     CHECK_EXIT(env);
1229     return result;
1230 }
1231
1232 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1233 {
1234     CHECK_ENTER(env, kFlag_Default);
1235     CHECK_CLASS(env, clazz);
1236     CHECK_UTF_STRING(env, message, true);
1237     jint result;
1238     result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1239     CHECK_EXIT(env);
1240     return result;
1241 }
1242
1243 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1244 {
1245     CHECK_ENTER(env, kFlag_ExcepOkay);
1246     jthrowable result;
1247     result = BASE_ENV(env)->ExceptionOccurred(env);
1248     CHECK_EXIT(env);
1249     return result;
1250 }
1251
1252 static void Check_ExceptionDescribe(JNIEnv* env)
1253 {
1254     CHECK_ENTER(env, kFlag_ExcepOkay);
1255     BASE_ENV(env)->ExceptionDescribe(env);
1256     CHECK_EXIT(env);
1257 }
1258
1259 static void Check_ExceptionClear(JNIEnv* env)
1260 {
1261     CHECK_ENTER(env, kFlag_ExcepOkay);
1262     BASE_ENV(env)->ExceptionClear(env);
1263     CHECK_EXIT(env);
1264 }
1265
1266 static void Check_FatalError(JNIEnv* env, const char* msg)
1267 {
1268     CHECK_ENTER(env, kFlag_Default);
1269     CHECK_UTF_STRING(env, msg, true);
1270     BASE_ENV(env)->FatalError(env, msg);
1271     CHECK_EXIT(env);
1272 }
1273
1274 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1275 {
1276     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1277     jint result;
1278     result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1279     CHECK_EXIT(env);
1280     return result;
1281 }
1282
1283 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1284 {
1285     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1286     CHECK_OBJECT(env, res);
1287     jobject result;
1288     result = BASE_ENV(env)->PopLocalFrame(env, res);
1289     CHECK_EXIT(env);
1290     return result;
1291 }
1292
1293 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1294 {
1295     CHECK_ENTER(env, kFlag_Default);
1296     CHECK_OBJECT(env, obj);
1297     jobject result;
1298     result = BASE_ENV(env)->NewGlobalRef(env, obj);
1299     CHECK_EXIT(env);
1300     return result;
1301 }
1302
1303 static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
1304 {
1305     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1306     CHECK_OBJECT(env, globalRef);
1307 #ifdef USE_INDIRECT_REF
1308     if (globalRef != NULL &&
1309         dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
1310     {
1311         LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)\n",
1312             globalRef, dvmGetJNIRefType(env, globalRef));
1313         abortMaybe();
1314     } else
1315 #endif
1316     {
1317         BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
1318     }
1319     CHECK_EXIT(env);
1320 }
1321
1322 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1323 {
1324     CHECK_ENTER(env, kFlag_Default);
1325     CHECK_OBJECT(env, ref);
1326     jobject result;
1327     result = BASE_ENV(env)->NewLocalRef(env, ref);
1328     CHECK_EXIT(env);
1329     return result;
1330 }
1331
1332 static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
1333 {
1334     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1335     CHECK_OBJECT(env, localRef);
1336 #ifdef USE_INDIRECT_REF
1337     if (localRef != NULL &&
1338         dvmGetJNIRefType(env, localRef) != JNILocalRefType)
1339     {
1340         LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)\n",
1341             localRef, dvmGetJNIRefType(env, localRef));
1342         abortMaybe();
1343     } else
1344 #endif
1345     {
1346         BASE_ENV(env)->DeleteLocalRef(env, localRef);
1347     }
1348     CHECK_EXIT(env);
1349 }
1350
1351 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1352 {
1353     CHECK_ENTER(env, kFlag_Default);
1354     jint result;
1355     result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1356     CHECK_EXIT(env);
1357     return result;
1358 }
1359
1360 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1361 {
1362     CHECK_ENTER(env, kFlag_Default);
1363     CHECK_OBJECT(env, ref1);
1364     CHECK_OBJECT(env, ref2);
1365     jboolean result;
1366     result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1367     CHECK_EXIT(env);
1368     return result;
1369 }
1370
1371 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1372 {
1373     CHECK_ENTER(env, kFlag_Default);
1374     CHECK_CLASS(env, clazz);
1375     jobject result;
1376     result = BASE_ENV(env)->AllocObject(env, clazz);
1377     CHECK_EXIT(env);
1378     return result;
1379 }
1380
1381 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1382     ...)
1383 {
1384     CHECK_ENTER(env, kFlag_Default);
1385     CHECK_CLASS(env, clazz);
1386     jobject result;
1387     va_list args;
1388
1389     va_start(args, methodID);
1390     result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1391     va_end(args);
1392
1393     CHECK_EXIT(env);
1394     return result;
1395 }
1396 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1397     va_list args)
1398 {
1399     CHECK_ENTER(env, kFlag_Default);
1400     CHECK_CLASS(env, clazz);
1401     jobject result;
1402     result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1403     CHECK_EXIT(env);
1404     return result;
1405 }
1406 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1407     jvalue* args)
1408 {
1409     CHECK_ENTER(env, kFlag_Default);
1410     CHECK_CLASS(env, clazz);
1411     jobject result;
1412     result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1413     CHECK_EXIT(env);
1414     return result;
1415 }
1416
1417 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1418 {
1419     CHECK_ENTER(env, kFlag_Default);
1420     CHECK_OBJECT(env, obj);
1421     jclass result;
1422     result = BASE_ENV(env)->GetObjectClass(env, obj);
1423     CHECK_EXIT(env);
1424     return result;
1425 }
1426
1427 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1428 {
1429     CHECK_ENTER(env, kFlag_Default);
1430     CHECK_OBJECT(env, obj);
1431     CHECK_CLASS(env, clazz);
1432     jboolean result;
1433     result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1434     CHECK_EXIT(env);
1435     return result;
1436 }
1437
1438 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1439     const char* sig)
1440 {
1441     CHECK_ENTER(env, kFlag_Default);
1442     CHECK_CLASS(env, clazz);
1443     CHECK_UTF_STRING(env, name, false);
1444     CHECK_UTF_STRING(env, sig, false);
1445     jmethodID result;
1446     result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1447     CHECK_EXIT(env);
1448     return result;
1449 }
1450
1451 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1452     const char* name, const char* sig)
1453 {
1454     CHECK_ENTER(env, kFlag_Default);
1455     CHECK_CLASS(env, clazz);
1456     CHECK_UTF_STRING(env, name, false);
1457     CHECK_UTF_STRING(env, sig, false);
1458     jfieldID result;
1459     result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1460     CHECK_EXIT(env);
1461     return result;
1462 }
1463
1464 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1465     const char* name, const char* sig)
1466 {
1467     CHECK_ENTER(env, kFlag_Default);
1468     CHECK_CLASS(env, clazz);
1469     CHECK_UTF_STRING(env, name, false);
1470     CHECK_UTF_STRING(env, sig, false);
1471     jmethodID result;
1472     result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1473     CHECK_EXIT(env);
1474     return result;
1475 }
1476
1477 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1478     const char* name, const char* sig)
1479 {
1480     CHECK_ENTER(env, kFlag_Default);
1481     CHECK_CLASS(env, clazz);
1482     CHECK_UTF_STRING(env, name, false);
1483     CHECK_UTF_STRING(env, sig, false);
1484     jfieldID result;
1485     result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1486     CHECK_EXIT(env);
1487     return result;
1488 }
1489
1490 #define GET_STATIC_TYPE_FIELD(_ctype, _jname)                               \
1491     static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1492         jfieldID fieldID)                                                   \
1493     {                                                                       \
1494         CHECK_ENTER(env, kFlag_Default);                                    \
1495         CHECK_CLASS(env, clazz);                                            \
1496         _ctype result;                                                      \
1497         checkStaticFieldID(env, clazz, fieldID);                            \
1498         result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz,        \
1499             fieldID);                                                       \
1500         CHECK_EXIT(env);                                                    \
1501         return result;                                                      \
1502     }
1503 GET_STATIC_TYPE_FIELD(jobject, Object);
1504 GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1505 GET_STATIC_TYPE_FIELD(jbyte, Byte);
1506 GET_STATIC_TYPE_FIELD(jchar, Char);
1507 GET_STATIC_TYPE_FIELD(jshort, Short);
1508 GET_STATIC_TYPE_FIELD(jint, Int);
1509 GET_STATIC_TYPE_FIELD(jlong, Long);
1510 GET_STATIC_TYPE_FIELD(jfloat, Float);
1511 GET_STATIC_TYPE_FIELD(jdouble, Double);
1512
1513 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype)                       \
1514     static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz,   \
1515         jfieldID fieldID, _ctype value)                                     \
1516     {                                                                       \
1517         CHECK_ENTER(env, kFlag_Default);                                    \
1518         CHECK_CLASS(env, clazz);                                            \
1519         checkStaticFieldID(env, clazz, fieldID);                            \
1520         /* "value" arg only used when type == ref */                        \
1521         CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true);   \
1522         BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID,        \
1523             value);                                                         \
1524         CHECK_EXIT(env);                                                    \
1525     }
1526 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1527 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1528 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1529 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1530 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1531 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1532 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1533 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1534 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1535
1536 #define GET_TYPE_FIELD(_ctype, _jname)                                      \
1537     static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj,        \
1538         jfieldID fieldID)                                                   \
1539     {                                                                       \
1540         CHECK_ENTER(env, kFlag_Default);                                    \
1541         CHECK_OBJECT(env, obj);                                             \
1542         _ctype result;                                                      \
1543         CHECK_INST_FIELD_ID(env, obj, fieldID);                             \
1544         result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID);      \
1545         CHECK_EXIT(env);                                                    \
1546         return result;                                                      \
1547     }
1548 GET_TYPE_FIELD(jobject, Object);
1549 GET_TYPE_FIELD(jboolean, Boolean);
1550 GET_TYPE_FIELD(jbyte, Byte);
1551 GET_TYPE_FIELD(jchar, Char);
1552 GET_TYPE_FIELD(jshort, Short);
1553 GET_TYPE_FIELD(jint, Int);
1554 GET_TYPE_FIELD(jlong, Long);
1555 GET_TYPE_FIELD(jfloat, Float);
1556 GET_TYPE_FIELD(jdouble, Double);
1557
1558 #define SET_TYPE_FIELD(_ctype, _jname, _ftype)                              \
1559     static void Check_Set##_jname##Field(JNIEnv* env, jobject obj,          \
1560         jfieldID fieldID, _ctype value)                                     \
1561     {                                                                       \
1562         CHECK_ENTER(env, kFlag_Default);                                    \
1563         CHECK_OBJECT(env, obj);                                             \
1564         CHECK_INST_FIELD_ID(env, obj, fieldID);                             \
1565         /* "value" arg only used when type == ref */                        \
1566         CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
1567         BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value);        \
1568         CHECK_EXIT(env);                                                    \
1569     }
1570 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1571 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1572 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1573 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1574 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1575 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1576 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1577 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1578 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1579
1580 #define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)   \
1581     static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj,      \
1582         jmethodID methodID, ...)                                            \
1583     {                                                                       \
1584         CHECK_ENTER(env, kFlag_Default);                                    \
1585         CHECK_OBJECT(env, obj);                                             \
1586         CHECK_SIG(env, methodID, _retsig, false);                           \
1587         _retdecl;                                                           \
1588         va_list args;                                                       \
1589         va_start(args, methodID);                                           \
1590         _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID,   \
1591             args);                                                          \
1592         va_end(args);                                                       \
1593         CHECK_EXIT(env);                                                    \
1594         return _retok;                                                      \
1595     }                                                                       \
1596     static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj,     \
1597         jmethodID methodID, va_list args)                                   \
1598     {                                                                       \
1599         CHECK_ENTER(env, kFlag_Default);                                    \
1600         CHECK_OBJECT(env, obj);                                             \
1601         CHECK_SIG(env, methodID, _retsig, false);                           \
1602         _retdecl;                                                           \
1603         _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID,   \
1604             args);                                                          \
1605         CHECK_EXIT(env);                                                    \
1606         return _retok;                                                      \
1607     }                                                                       \
1608     static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj,     \
1609         jmethodID methodID, jvalue* args)                                   \
1610     {                                                                       \
1611         CHECK_ENTER(env, kFlag_Default);                                    \
1612         CHECK_OBJECT(env, obj);                                             \
1613         CHECK_SIG(env, methodID, _retsig, false);                           \
1614         _retdecl;                                                           \
1615         _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID,   \
1616             args);                                                          \
1617         CHECK_EXIT(env);                                                    \
1618         return _retok;                                                      \
1619     }
1620 CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1621 CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1622 CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1623 CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1624 CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1625 CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
1626 CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1627 CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1628 CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1629 CALL_VIRTUAL(void, Void, , , , 'V');
1630
1631 #define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok,         \
1632         _retsig)                                                            \
1633     static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env,         \
1634         jobject obj, jclass clazz, jmethodID methodID, ...)                 \
1635     {                                                                       \
1636         CHECK_ENTER(env, kFlag_Default);                                    \
1637         CHECK_CLASS(env, clazz);                                            \
1638         CHECK_OBJECT(env, obj);                                             \
1639         CHECK_SIG(env, methodID, _retsig, false);                           \
1640         _retdecl;                                                           \
1641         va_list args;                                                       \
1642         va_start(args, methodID);                                           \
1643         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1644             clazz, methodID, args);                                         \
1645         va_end(args);                                                       \
1646         CHECK_EXIT(env);                                                    \
1647         return _retok;                                                      \
1648     }                                                                       \
1649     static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env,        \
1650         jobject obj, jclass clazz, jmethodID methodID, va_list args)        \
1651     {                                                                       \
1652         CHECK_ENTER(env, kFlag_Default);                                    \
1653         CHECK_CLASS(env, clazz);                                            \
1654         CHECK_OBJECT(env, obj);                                             \
1655         CHECK_SIG(env, methodID, _retsig, false);                           \
1656         _retdecl;                                                           \
1657         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj,   \
1658             clazz, methodID, args);                                         \
1659         CHECK_EXIT(env);                                                    \
1660         return _retok;                                                      \
1661     }                                                                       \
1662     static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env,        \
1663         jobject obj, jclass clazz, jmethodID methodID, jvalue* args)        \
1664     {                                                                       \
1665         CHECK_ENTER(env, kFlag_Default);                                    \
1666         CHECK_CLASS(env, clazz);                                            \
1667         CHECK_OBJECT(env, obj);                                             \
1668         CHECK_SIG(env, methodID, _retsig, false);                           \
1669         _retdecl;                                                           \
1670         _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj,   \
1671             clazz, methodID, args);                                         \
1672         CHECK_EXIT(env);                                                    \
1673         return _retok;                                                      \
1674     }
1675 CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1676 CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1677 CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1678 CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1679 CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1680 CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
1681 CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1682 CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1683 CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1684 CALL_NONVIRTUAL(void, Void, , , , 'V');
1685
1686
1687 #define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig)    \
1688     static _ctype Check_CallStatic##_jname##Method(JNIEnv* env,             \
1689         jclass clazz, jmethodID methodID, ...)                              \
1690     {                                                                       \
1691         CHECK_ENTER(env, kFlag_Default);                                    \
1692         CHECK_CLASS(env, clazz);                                            \
1693         CHECK_SIG(env, methodID, _retsig, true);                            \
1694         _retdecl;                                                           \
1695         va_list args;                                                       \
1696         va_start(args, methodID);                                           \
1697         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz,     \
1698             methodID, args);                                                \
1699         va_end(args);                                                       \
1700         CHECK_EXIT(env);                                                    \
1701         return _retok;                                                      \
1702     }                                                                       \
1703     static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env,            \
1704         jclass clazz, jmethodID methodID, va_list args)                     \
1705     {                                                                       \
1706         CHECK_ENTER(env, kFlag_Default);                                    \
1707         CHECK_CLASS(env, clazz);                                            \
1708         CHECK_SIG(env, methodID, _retsig, true);                            \
1709         _retdecl;                                                           \
1710         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz,     \
1711             methodID, args);                                                \
1712         CHECK_EXIT(env);                                                    \
1713         return _retok;                                                      \
1714     }                                                                       \
1715     static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env,            \
1716         jclass clazz, jmethodID methodID, jvalue* args)                     \
1717     {                                                                       \
1718         CHECK_ENTER(env, kFlag_Default);                                    \
1719         CHECK_CLASS(env, clazz);                                            \
1720         CHECK_SIG(env, methodID, _retsig, true);                            \
1721         _retdecl;                                                           \
1722         _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz,     \
1723             methodID, args);                                                \
1724         CHECK_EXIT(env);                                                    \
1725         return _retok;                                                      \
1726     }
1727 CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
1728 CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
1729 CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
1730 CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
1731 CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
1732 CALL_STATIC(jint, Int, jint result, result=, result, 'I');
1733 CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
1734 CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
1735 CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
1736 CALL_STATIC(void, Void, , , , 'V');
1737
1738 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1739     jsize len)
1740 {
1741     CHECK_ENTER(env, kFlag_Default);
1742     jstring result;
1743     result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1744     CHECK_EXIT(env);
1745     return result;
1746 }
1747
1748 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1749 {
1750     CHECK_ENTER(env, kFlag_CritOkay);
1751     CHECK_STRING(env, string);
1752     jsize result;
1753     result = BASE_ENV(env)->GetStringLength(env, string);
1754     CHECK_EXIT(env);
1755     return result;
1756 }
1757
1758 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1759     jboolean* isCopy)
1760 {
1761     CHECK_ENTER(env, kFlag_CritOkay);
1762     CHECK_STRING(env, string);
1763     const jchar* result;
1764     result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1765     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1766         // TODO: fix for indirect
1767         int len = dvmStringLen(string) * 2;
1768         result = (const jchar*) createGuardedCopy(result, len, false);
1769         if (isCopy != NULL)
1770             *isCopy = JNI_TRUE;
1771     }
1772     CHECK_EXIT(env);
1773     return result;
1774 }
1775
1776 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1777     const jchar* chars)
1778 {
1779     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1780     CHECK_STRING(env, string);
1781     CHECK_NON_NULL(env, chars);
1782     if (((JNIEnvExt*)env)->forceDataCopy) {
1783         if (!checkGuardedCopy(chars, false)) {
1784             LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1785             abortMaybe();
1786             return;
1787         }
1788         chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1789     }
1790     BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1791     CHECK_EXIT(env);
1792 }
1793
1794 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1795 {
1796     CHECK_ENTER(env, kFlag_Default);
1797     CHECK_UTF_STRING(env, bytes, true);
1798     jstring result;
1799     result = BASE_ENV(env)->NewStringUTF(env, bytes);
1800     CHECK_EXIT(env);
1801     return result;
1802 }
1803
1804 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1805 {
1806     CHECK_ENTER(env, kFlag_CritOkay);
1807     CHECK_STRING(env, string);
1808     jsize result;
1809     result = BASE_ENV(env)->GetStringUTFLength(env, string);
1810     CHECK_EXIT(env);
1811     return result;
1812 }
1813
1814 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1815     jboolean* isCopy)
1816 {
1817     CHECK_ENTER(env, kFlag_CritOkay);
1818     CHECK_STRING(env, string);
1819     const char* result;
1820     result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1821     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1822         // TODO: fix for indirect
1823         int len = dvmStringUtf8ByteLen(string) + 1;
1824         result = (const char*) createGuardedCopy(result, len, false);
1825         if (isCopy != NULL)
1826             *isCopy = JNI_TRUE;
1827     }
1828     CHECK_EXIT(env);
1829     return result;
1830 }
1831
1832 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1833     const char* utf)
1834 {
1835     CHECK_ENTER(env, kFlag_ExcepOkay);
1836     CHECK_STRING(env, string);
1837     CHECK_NON_NULL(env, utf);
1838     if (((JNIEnvExt*)env)->forceDataCopy) {
1839         //int len = dvmStringUtf8ByteLen(string) + 1;
1840         if (!checkGuardedCopy(utf, false)) {
1841             LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1842             abortMaybe();
1843             return;
1844         }
1845         utf = (const char*) freeGuardedCopy((char*)utf);
1846     }
1847     BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1848     CHECK_EXIT(env);
1849 }
1850
1851 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1852 {
1853     CHECK_ENTER(env, kFlag_CritOkay);
1854     CHECK_ARRAY(env, array);
1855     jsize result;
1856     result = BASE_ENV(env)->GetArrayLength(env, array);
1857     CHECK_EXIT(env);
1858     return result;
1859 }
1860
1861 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1862     jclass elementClass, jobject initialElement)
1863 {
1864     CHECK_ENTER(env, kFlag_Default);
1865     CHECK_CLASS(env, elementClass);
1866     CHECK_OBJECT(env, initialElement);
1867     CHECK_LENGTH_POSITIVE(env, length);
1868     jobjectArray result;
1869     result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
1870                                             initialElement);
1871     CHECK_EXIT(env);
1872     return result;
1873 }
1874
1875 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
1876     jsize index)
1877 {
1878     CHECK_ENTER(env, kFlag_Default);
1879     CHECK_ARRAY(env, array);
1880     jobject result;
1881     result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
1882     CHECK_EXIT(env);
1883     return result;
1884 }
1885
1886 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
1887     jsize index, jobject value)
1888 {
1889     CHECK_ENTER(env, kFlag_Default);
1890     CHECK_ARRAY(env, array);
1891     BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
1892     CHECK_EXIT(env);
1893 }
1894
1895 #define NEW_PRIMITIVE_ARRAY(_artype, _jname)                                \
1896     static _artype Check_New##_jname##Array(JNIEnv* env, jsize length)      \
1897     {                                                                       \
1898         CHECK_ENTER(env, kFlag_Default);                                    \
1899         CHECK_LENGTH_POSITIVE(env, length);                                 \
1900         _artype result;                                                     \
1901         result = BASE_ENV(env)->New##_jname##Array(env, length);            \
1902         CHECK_EXIT(env);                                                    \
1903         return result;                                                      \
1904     }
1905 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1906 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1907 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1908 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1909 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1910 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1911 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1912 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1913
1914
1915 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                        \
1916     static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env,            \
1917         _ctype##Array array, jboolean* isCopy)                              \
1918     {                                                                       \
1919         CHECK_ENTER(env, kFlag_Default);                                    \
1920         CHECK_ARRAY(env, array);                                            \
1921         _ctype* result;                                                     \
1922         result = BASE_ENV(env)->Get##_jname##ArrayElements(env,             \
1923             array, isCopy);                                                 \
1924         if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {           \
1925             result = (_ctype*) createGuardedPACopy(env, array, isCopy);     \
1926         }                                                                   \
1927         CHECK_EXIT(env);                                                    \
1928         return result;                                                      \
1929     }
1930
1931 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname)                    \
1932     static void Check_Release##_jname##ArrayElements(JNIEnv* env,           \
1933         _ctype##Array array, _ctype* elems, jint mode)                      \
1934     {                                                                       \
1935         CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);                  \
1936         CHECK_ARRAY(env, array);                                            \
1937         CHECK_NON_NULL(env, elems);                                         \
1938         CHECK_RELEASE_MODE(env, mode);                                      \
1939         if (((JNIEnvExt*)env)->forceDataCopy) {                             \
1940             elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
1941         }                                                                   \
1942         BASE_ENV(env)->Release##_jname##ArrayElements(env,                  \
1943             array, elems, mode);                                            \
1944         CHECK_EXIT(env);                                                    \
1945     }
1946
1947 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
1948     static void Check_Get##_jname##ArrayRegion(JNIEnv* env,                 \
1949         _ctype##Array array, jsize start, jsize len, _ctype* buf)           \
1950     {                                                                       \
1951         CHECK_ENTER(env, kFlag_Default);                                    \
1952         CHECK_ARRAY(env, array);                                            \
1953         BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start,          \
1954             len, buf);                                                      \
1955         CHECK_EXIT(env);                                                    \
1956     }
1957
1958 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname)                          \
1959     static void Check_Set##_jname##ArrayRegion(JNIEnv* env,                 \
1960         _ctype##Array array, jsize start, jsize len, const _ctype* buf)     \
1961     {                                                                       \
1962         CHECK_ENTER(env, kFlag_Default);                                    \
1963         CHECK_ARRAY(env, array);                                            \
1964         BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start,          \
1965             len, buf);                                                      \
1966         CHECK_EXIT(env);                                                    \
1967     }
1968
1969 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar)                \
1970     GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                           \
1971     RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname);                       \
1972     GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);                             \
1973     SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1974
1975 /* TODO: verify primitive array type matches call type */
1976 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1977 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1978 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1979 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1980 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1981 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1982 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1983 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1984
1985 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
1986     const JNINativeMethod* methods, jint nMethods)
1987 {
1988     CHECK_ENTER(env, kFlag_Default);
1989     CHECK_CLASS(env, clazz);
1990     jint result;
1991     result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
1992     CHECK_EXIT(env);
1993     return result;
1994 }
1995
1996 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
1997 {
1998     CHECK_ENTER(env, kFlag_Default);
1999     CHECK_CLASS(env, clazz);
2000     jint result;
2001     result = BASE_ENV(env)->UnregisterNatives(env, clazz);
2002     CHECK_EXIT(env);
2003     return result;
2004 }
2005
2006 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
2007 {
2008     CHECK_ENTER(env, kFlag_Default);
2009     CHECK_OBJECT(env, obj);
2010     jint result;
2011     result = BASE_ENV(env)->MonitorEnter(env, obj);
2012     CHECK_EXIT(env);
2013     return result;
2014 }
2015
2016 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
2017 {
2018     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2019     CHECK_OBJECT(env, obj);
2020     jint result;
2021     result = BASE_ENV(env)->MonitorExit(env, obj);
2022     CHECK_EXIT(env);
2023     return result;
2024 }
2025
2026 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
2027 {
2028     CHECK_ENTER(env, kFlag_Default);
2029     jint result;
2030     result = BASE_ENV(env)->GetJavaVM(env, vm);
2031     CHECK_EXIT(env);
2032     return result;
2033 }
2034
2035 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
2036     jsize len, jchar* buf)
2037 {
2038     CHECK_ENTER(env, kFlag_CritOkay);
2039     CHECK_STRING(env, str);
2040     BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
2041     CHECK_EXIT(env);
2042 }
2043
2044 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
2045     jsize len, char* buf)
2046 {
2047     CHECK_ENTER(env, kFlag_CritOkay);
2048     CHECK_STRING(env, str);
2049     BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
2050     CHECK_EXIT(env);
2051 }
2052
2053 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
2054     jboolean* isCopy)
2055 {
2056     CHECK_ENTER(env, kFlag_CritGet);
2057     CHECK_ARRAY(env, array);
2058     void* result;
2059     result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
2060     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2061         result = createGuardedPACopy(env, array, isCopy);
2062     }
2063     CHECK_EXIT(env);
2064     return result;
2065 }
2066
2067 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
2068     void* carray, jint mode)
2069 {
2070     CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2071     CHECK_ARRAY(env, array);
2072     CHECK_NON_NULL(env, carray);
2073     CHECK_RELEASE_MODE(env, mode);
2074     if (((JNIEnvExt*)env)->forceDataCopy) {
2075         carray = releaseGuardedPACopy(env, array, carray, mode);
2076     }
2077     BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2078     CHECK_EXIT(env);
2079 }
2080
2081 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
2082     jboolean* isCopy)
2083 {
2084     CHECK_ENTER(env, kFlag_CritGet);
2085     CHECK_STRING(env, string);
2086     const jchar* result;
2087     result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
2088     if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2089         // TODO: fix for indirect
2090         int len = dvmStringLen(string) * 2;
2091         result = (const jchar*) createGuardedCopy(result, len, false);
2092         if (isCopy != NULL)
2093             *isCopy = JNI_TRUE;
2094     }
2095     CHECK_EXIT(env);
2096     return result;
2097 }
2098
2099 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
2100     const jchar* carray)
2101 {
2102     CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2103     CHECK_STRING(env, string);
2104     CHECK_NON_NULL(env, carray);
2105     if (((JNIEnvExt*)env)->forceDataCopy) {
2106         if (!checkGuardedCopy(carray, false)) {
2107             LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
2108             abortMaybe();
2109             return;
2110         }
2111         carray = (const jchar*) freeGuardedCopy((jchar*)carray);
2112     }
2113     BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
2114     CHECK_EXIT(env);
2115 }
2116
2117 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
2118 {
2119     CHECK_ENTER(env, kFlag_Default);
2120     CHECK_OBJECT(env, obj);
2121     jweak result;
2122     result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
2123     CHECK_EXIT(env);
2124     return result;
2125 }
2126
2127 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
2128 {
2129     CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2130     CHECK_OBJECT(env, obj);
2131     BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
2132     CHECK_EXIT(env);
2133 }
2134
2135 static jboolean Check_ExceptionCheck(JNIEnv* env)
2136 {
2137     CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
2138     jboolean result;
2139     result = BASE_ENV(env)->ExceptionCheck(env);
2140     CHECK_EXIT(env);
2141     return result;
2142 }
2143
2144 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
2145 {
2146     CHECK_ENTER(env, kFlag_Default);
2147     CHECK_OBJECT(env, obj);
2148     jobjectRefType result;
2149     result = BASE_ENV(env)->GetObjectRefType(env, obj);
2150     CHECK_EXIT(env);
2151     return result;
2152 }
2153
2154 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
2155     jlong capacity)
2156 {
2157     CHECK_ENTER(env, kFlag_Default);
2158     jobject result;
2159     if (address == NULL || capacity < 0) {
2160         LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
2161             address, (long) capacity);
2162         abortMaybe();
2163         return NULL;
2164     }
2165     result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
2166     CHECK_EXIT(env);
2167     return result;
2168 }
2169
2170 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
2171 {
2172     CHECK_ENTER(env, kFlag_Default);
2173     CHECK_OBJECT(env, buf);
2174     void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
2175     CHECK_EXIT(env);
2176
2177     /* optional - check result vs. "safe" implementation */
2178     if (kRedundantDirectBufferTest) {
2179         jobject platformAddr = NULL;
2180         void* checkResult = NULL;
2181
2182         /*
2183          * Start by determining if the object supports the DirectBuffer
2184          * interfaces.  Note this does not guarantee that it's a direct buffer.
2185          */
2186         if (JNI_FALSE == (*env)->IsInstanceOf(env, buf,
2187                 gDvm.jclassOrgApacheHarmonyNioInternalDirectBuffer))
2188         {
2189             goto bail;
2190         }
2191
2192         /*
2193          * Get the PlatformAddress object.
2194          *
2195          * If this isn't a direct buffer, platformAddr will be NULL and/or an
2196          * exception will have been thrown.
2197          */
2198         platformAddr = (*env)->CallObjectMethod(env, buf,
2199             (jmethodID) gDvm.methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress);
2200
2201         if ((*env)->ExceptionCheck(env)) {
2202             (*env)->ExceptionClear(env);
2203             platformAddr = NULL;
2204         }
2205         if (platformAddr == NULL) {
2206             LOGV("Got request for address of non-direct buffer\n");
2207             goto bail;
2208         }
2209
2210         jclass platformAddrClass = (*env)->FindClass(env,
2211             "org/apache/harmony/luni/platform/PlatformAddress");
2212         jmethodID toLongMethod = (*env)->GetMethodID(env, platformAddrClass,
2213             "toLong", "()J");
2214         checkResult = (void*)(u4)(*env)->CallLongMethod(env, platformAddr,
2215                 toLongMethod);
2216
2217     bail:
2218         if (platformAddr != NULL)
2219             (*env)->DeleteLocalRef(env, platformAddr);
2220
2221         if (result != checkResult) {
2222             LOGW("JNI WARNING: direct buffer result mismatch (%p vs %p)\n",
2223                 result, checkResult);
2224             abortMaybe();
2225             /* keep going */
2226         }
2227     }
2228
2229     return result;
2230 }
2231
2232 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
2233 {
2234     CHECK_ENTER(env, kFlag_Default);
2235     CHECK_OBJECT(env, buf);
2236     /* TODO: verify "buf" is an instance of java.nio.Buffer */
2237     jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2238     CHECK_EXIT(env);
2239     return result;
2240 }
2241
2242
2243 /*
2244  * ===========================================================================
2245  *      JNI invocation functions
2246  * ===========================================================================
2247  */
2248
2249 static jint Check_DestroyJavaVM(JavaVM* vm)
2250 {
2251     CHECK_VMENTER(vm, false);
2252     jint result;
2253     result = BASE_VM(vm)->DestroyJavaVM(vm);
2254     CHECK_VMEXIT(vm, false);
2255     return result;
2256 }
2257
2258 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2259     void* thr_args)
2260 {
2261     CHECK_VMENTER(vm, false);
2262     jint result;
2263     result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2264     CHECK_VMEXIT(vm, true);
2265     return result;
2266 }
2267
2268 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2269     void* thr_args)
2270 {
2271     CHECK_VMENTER(vm, false);
2272     jint result;
2273     result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2274     CHECK_VMEXIT(vm, true);
2275     return result;
2276 }
2277
2278 static jint Check_DetachCurrentThread(JavaVM* vm)
2279 {
2280     CHECK_VMENTER(vm, true);
2281     jint result;
2282     result = BASE_VM(vm)->DetachCurrentThread(vm);
2283     CHECK_VMEXIT(vm, false);
2284     return result;
2285 }
2286
2287 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2288 {
2289     CHECK_VMENTER(vm, true);
2290     jint result;
2291     result = BASE_VM(vm)->GetEnv(vm, env, version);
2292     CHECK_VMEXIT(vm, true);
2293     return result;
2294 }
2295
2296
2297 /*
2298  * ===========================================================================
2299  *      Function tables
2300  * ===========================================================================
2301  */
2302
2303 static const struct JNINativeInterface gCheckNativeInterface = {
2304     NULL,
2305     NULL,
2306     NULL,
2307     NULL,
2308
2309     Check_GetVersion,
2310
2311     Check_DefineClass,
2312     Check_FindClass,
2313
2314     Check_FromReflectedMethod,
2315     Check_FromReflectedField,
2316     Check_ToReflectedMethod,
2317
2318     Check_GetSuperclass,
2319     Check_IsAssignableFrom,
2320
2321     Check_ToReflectedField,
2322
2323     Check_Throw,
2324     Check_ThrowNew,
2325     Check_ExceptionOccurred,
2326     Check_ExceptionDescribe,
2327     Check_ExceptionClear,
2328     Check_FatalError,
2329
2330     Check_PushLocalFrame,
2331     Check_PopLocalFrame,
2332
2333     Check_NewGlobalRef,
2334     Check_DeleteGlobalRef,
2335     Check_DeleteLocalRef,
2336     Check_IsSameObject,
2337     Check_NewLocalRef,
2338     Check_EnsureLocalCapacity,
2339
2340     Check_AllocObject,
2341     Check_NewObject,
2342     Check_NewObjectV,
2343     Check_NewObjectA,
2344
2345     Check_GetObjectClass,
2346     Check_IsInstanceOf,
2347
2348     Check_GetMethodID,
2349
2350     Check_CallObjectMethod,
2351     Check_CallObjectMethodV,
2352     Check_CallObjectMethodA,
2353     Check_CallBooleanMethod,
2354     Check_CallBooleanMethodV,
2355     Check_CallBooleanMethodA,
2356     Check_CallByteMethod,
2357     Check_CallByteMethodV,
2358     Check_CallByteMethodA,
2359     Check_CallCharMethod,
2360     Check_CallCharMethodV,
2361     Check_CallCharMethodA,
2362     Check_CallShortMethod,
2363     Check_CallShortMethodV,
2364     Check_CallShortMethodA,
2365     Check_CallIntMethod,
2366     Check_CallIntMethodV,
2367     Check_CallIntMethodA,
2368     Check_CallLongMethod,
2369     Check_CallLongMethodV,
2370     Check_CallLongMethodA,
2371     Check_CallFloatMethod,
2372     Check_CallFloatMethodV,
2373     Check_CallFloatMethodA,
2374     Check_CallDoubleMethod,
2375     Check_CallDoubleMethodV,
2376     Check_CallDoubleMethodA,
2377     Check_CallVoidMethod,
2378     Check_CallVoidMethodV,
2379     Check_CallVoidMethodA,
2380
2381     Check_CallNonvirtualObjectMethod,
2382     Check_CallNonvirtualObjectMethodV,
2383     Check_CallNonvirtualObjectMethodA,
2384     Check_CallNonvirtualBooleanMethod,
2385     Check_CallNonvirtualBooleanMethodV,
2386     Check_CallNonvirtualBooleanMethodA,
2387     Check_CallNonvirtualByteMethod,
2388     Check_CallNonvirtualByteMethodV,
2389     Check_CallNonvirtualByteMethodA,
2390     Check_CallNonvirtualCharMethod,
2391     Check_CallNonvirtualCharMethodV,
2392     Check_CallNonvirtualCharMethodA,
2393     Check_CallNonvirtualShortMethod,
2394     Check_CallNonvirtualShortMethodV,
2395     Check_CallNonvirtualShortMethodA,
2396     Check_CallNonvirtualIntMethod,
2397     Check_CallNonvirtualIntMethodV,
2398     Check_CallNonvirtualIntMethodA,
2399     Check_CallNonvirtualLongMethod,
2400     Check_CallNonvirtualLongMethodV,
2401     Check_CallNonvirtualLongMethodA,
2402     Check_CallNonvirtualFloatMethod,
2403     Check_CallNonvirtualFloatMethodV,
2404     Check_CallNonvirtualFloatMethodA,
2405     Check_CallNonvirtualDoubleMethod,
2406     Check_CallNonvirtualDoubleMethodV,
2407     Check_CallNonvirtualDoubleMethodA,
2408     Check_CallNonvirtualVoidMethod,
2409     Check_CallNonvirtualVoidMethodV,
2410     Check_CallNonvirtualVoidMethodA,
2411
2412     Check_GetFieldID,
2413
2414     Check_GetObjectField,
2415     Check_GetBooleanField,
2416     Check_GetByteField,
2417     Check_GetCharField,
2418     Check_GetShortField,
2419     Check_GetIntField,
2420     Check_GetLongField,
2421     Check_GetFloatField,
2422     Check_GetDoubleField,
2423     Check_SetObjectField,
2424     Check_SetBooleanField,
2425     Check_SetByteField,
2426     Check_SetCharField,
2427     Check_SetShortField,
2428     Check_SetIntField,
2429     Check_SetLongField,
2430     Check_SetFloatField,
2431     Check_SetDoubleField,
2432
2433     Check_GetStaticMethodID,
2434
2435     Check_CallStaticObjectMethod,
2436     Check_CallStaticObjectMethodV,
2437     Check_CallStaticObjectMethodA,
2438     Check_CallStaticBooleanMethod,
2439     Check_CallStaticBooleanMethodV,
2440     Check_CallStaticBooleanMethodA,
2441     Check_CallStaticByteMethod,
2442     Check_CallStaticByteMethodV,
2443     Check_CallStaticByteMethodA,
2444     Check_CallStaticCharMethod,
2445     Check_CallStaticCharMethodV,
2446     Check_CallStaticCharMethodA,
2447     Check_CallStaticShortMethod,
2448     Check_CallStaticShortMethodV,
2449     Check_CallStaticShortMethodA,
2450     Check_CallStaticIntMethod,
2451     Check_CallStaticIntMethodV,
2452     Check_CallStaticIntMethodA,
2453     Check_CallStaticLongMethod,
2454     Check_CallStaticLongMethodV,
2455     Check_CallStaticLongMethodA,
2456     Check_CallStaticFloatMethod,
2457     Check_CallStaticFloatMethodV,
2458     Check_CallStaticFloatMethodA,
2459     Check_CallStaticDoubleMethod,
2460     Check_CallStaticDoubleMethodV,
2461     Check_CallStaticDoubleMethodA,
2462     Check_CallStaticVoidMethod,
2463     Check_CallStaticVoidMethodV,
2464     Check_CallStaticVoidMethodA,
2465
2466     Check_GetStaticFieldID,
2467
2468     Check_GetStaticObjectField,
2469     Check_GetStaticBooleanField,
2470     Check_GetStaticByteField,
2471     Check_GetStaticCharField,
2472     Check_GetStaticShortField,
2473     Check_GetStaticIntField,
2474     Check_GetStaticLongField,
2475     Check_GetStaticFloatField,
2476     Check_GetStaticDoubleField,
2477
2478     Check_SetStaticObjectField,
2479     Check_SetStaticBooleanField,
2480     Check_SetStaticByteField,
2481     Check_SetStaticCharField,
2482     Check_SetStaticShortField,
2483     Check_SetStaticIntField,
2484     Check_SetStaticLongField,
2485     Check_SetStaticFloatField,
2486     Check_SetStaticDoubleField,
2487
2488     Check_NewString,
2489
2490     Check_GetStringLength,
2491     Check_GetStringChars,
2492     Check_ReleaseStringChars,
2493
2494     Check_NewStringUTF,
2495     Check_GetStringUTFLength,
2496     Check_GetStringUTFChars,
2497     Check_ReleaseStringUTFChars,
2498
2499     Check_GetArrayLength,
2500     Check_NewObjectArray,
2501     Check_GetObjectArrayElement,
2502     Check_SetObjectArrayElement,
2503
2504     Check_NewBooleanArray,
2505     Check_NewByteArray,
2506     Check_NewCharArray,
2507     Check_NewShortArray,
2508     Check_NewIntArray,
2509     Check_NewLongArray,
2510     Check_NewFloatArray,
2511     Check_NewDoubleArray,
2512
2513     Check_GetBooleanArrayElements,
2514     Check_GetByteArrayElements,
2515     Check_GetCharArrayElements,
2516     Check_GetShortArrayElements,
2517     Check_GetIntArrayElements,
2518     Check_GetLongArrayElements,
2519     Check_GetFloatArrayElements,
2520     Check_GetDoubleArrayElements,
2521
2522     Check_ReleaseBooleanArrayElements,
2523     Check_ReleaseByteArrayElements,
2524     Check_ReleaseCharArrayElements,
2525     Check_ReleaseShortArrayElements,
2526     Check_ReleaseIntArrayElements,
2527     Check_ReleaseLongArrayElements,
2528     Check_ReleaseFloatArrayElements,
2529     Check_ReleaseDoubleArrayElements,
2530
2531     Check_GetBooleanArrayRegion,
2532     Check_GetByteArrayRegion,
2533     Check_GetCharArrayRegion,
2534     Check_GetShortArrayRegion,
2535     Check_GetIntArrayRegion,
2536     Check_GetLongArrayRegion,
2537     Check_GetFloatArrayRegion,
2538     Check_GetDoubleArrayRegion,
2539     Check_SetBooleanArrayRegion,
2540     Check_SetByteArrayRegion,
2541     Check_SetCharArrayRegion,
2542     Check_SetShortArrayRegion,
2543     Check_SetIntArrayRegion,
2544     Check_SetLongArrayRegion,
2545     Check_SetFloatArrayRegion,
2546     Check_SetDoubleArrayRegion,
2547
2548     Check_RegisterNatives,
2549     Check_UnregisterNatives,
2550
2551     Check_MonitorEnter,
2552     Check_MonitorExit,
2553
2554     Check_GetJavaVM,
2555
2556     Check_GetStringRegion,
2557     Check_GetStringUTFRegion,
2558
2559     Check_GetPrimitiveArrayCritical,
2560     Check_ReleasePrimitiveArrayCritical,
2561
2562     Check_GetStringCritical,
2563     Check_ReleaseStringCritical,
2564
2565     Check_NewWeakGlobalRef,
2566     Check_DeleteWeakGlobalRef,
2567
2568     Check_ExceptionCheck,
2569
2570     Check_NewDirectByteBuffer,
2571     Check_GetDirectBufferAddress,
2572     Check_GetDirectBufferCapacity,
2573
2574     Check_GetObjectRefType
2575 };
2576 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2577     NULL,
2578     NULL,
2579     NULL,
2580
2581     Check_DestroyJavaVM,
2582     Check_AttachCurrentThread,
2583     Check_DetachCurrentThread,
2584
2585     Check_GetEnv,
2586
2587     Check_AttachCurrentThreadAsDaemon,
2588 };
2589
2590
2591 /*
2592  * Replace the normal table with the checked table.
2593  */
2594 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2595 {
2596     assert(pEnv->funcTable != &gCheckNativeInterface);
2597     pEnv->baseFuncTable = pEnv->funcTable;
2598     pEnv->funcTable = &gCheckNativeInterface;
2599 }
2600
2601 /*
2602  * Replace the normal table with the checked table.
2603  */
2604 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2605 {
2606     assert(pVm->funcTable != &gCheckInvokeInterface);
2607     pVm->baseFuncTable = pVm->funcTable;
2608     pVm->funcTable = &gCheckInvokeInterface;
2609 }