OSDN Git Service

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