2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Support for -Xcheck:jni (the "careful" version of the JNI interfaces).
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.
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
30 * TODO: verify that the methodID passed into the Call functions is for
31 * a method in the specified class.
34 #include "JniInternal.h"
38 #define JNI_ENTER() dvmChangeStatus(NULL, THREAD_RUNNING)
39 #define JNI_EXIT() dvmChangeStatus(NULL, THREAD_NATIVE)
41 #define BASE_ENV(_env) (((JNIEnvExt*)_env)->baseFuncTable)
42 #define BASE_VM(_vm) (((JavaVMExt*)_vm)->baseFuncTable)
45 * Flags passed into checkThread().
47 #define kFlag_Default 0x0000
49 #define kFlag_CritBad 0x0000 /* calling while in critical is bad */
50 #define kFlag_CritOkay 0x0001 /* ...okay */
51 #define kFlag_CritGet 0x0002 /* this is a critical "get" */
52 #define kFlag_CritRelease 0x0003 /* this is a critical "release" */
53 #define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
55 #define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
56 #define kFlag_ExcepOkay 0x0004 /* ...okay */
59 * Enter/exit macros for JNI env "check" functions. These do not change
60 * the thread state within the VM.
62 #define CHECK_ENTER(_env, _flags) \
64 JNI_TRACE(true, true); \
65 checkThread(_env, _flags, __FUNCTION__); \
68 #define CHECK_EXIT(_env) \
69 do { JNI_TRACE(false, true); } while(false)
73 * Enter/exit macros for JNI invocation interface "check" functions. These
74 * do not change the thread state within the VM.
76 * Set "_hasmeth" to true if we have a valid thread with a method pointer.
77 * We won't have one before attaching a thread, after detaching a thread, or
78 * after destroying the VM.
80 #define CHECK_VMENTER(_vm, _hasmeth) \
81 do { JNI_TRACE(true, _hasmeth); } while(false)
82 #define CHECK_VMEXIT(_vm, _hasmeth) \
83 do { JNI_TRACE(false, _hasmeth); } while(false)
85 #define CHECK_FIELD_TYPE(_obj, _fieldid, _prim, _isstatic) \
86 checkFieldType(_obj, _fieldid, _prim, _isstatic, __FUNCTION__)
87 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid) \
88 checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
89 #define CHECK_CLASS(_env, _clazz) \
90 checkClass(_env, _clazz, __FUNCTION__)
91 #define CHECK_STRING(_env, _str) \
92 checkString(_env, _str, __FUNCTION__)
93 #define CHECK_UTF_STRING(_env, _str, _nullok) \
94 checkUtfString(_env, _str, _nullok, __FUNCTION__)
95 #define CHECK_CLASS_NAME(_env, _str) \
96 checkClassName(_env, _str, __FUNCTION__)
97 #define CHECK_OBJECT(_env, _obj) \
98 checkObject(_env, _obj, __FUNCTION__)
99 #define CHECK_ARRAY(_env, _array) \
100 checkArray(_env, _array, __FUNCTION__)
101 #define CHECK_RELEASE_MODE(_env, _mode) \
102 checkReleaseMode(_env, _mode, __FUNCTION__)
103 #define CHECK_LENGTH_POSITIVE(_env, _length) \
104 checkLengthPositive(_env, _length, __FUNCTION__)
105 #define CHECK_NON_NULL(_env, _ptr) \
106 checkNonNull(_env, _ptr, __FUNCTION__)
108 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic) \
109 checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
112 * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
114 #define JNI_TRACE(_entry, _hasmeth) \
116 if (gDvm.verboseJni && (_entry)) { \
117 static const char* classDescriptor = "???"; \
118 static const char* methodName = "???"; \
120 const Method* meth = dvmGetCurrentJNIMethod(); \
121 classDescriptor = meth->clazz->descriptor; \
122 methodName = meth->name; \
124 /* use +6 to drop the leading "Check_" */ \
125 LOGI("JNI: %s (from %s.%s)", \
126 (__FUNCTION__)+6, classDescriptor, methodName); \
131 * Log the current location.
133 * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
135 static void showLocation(const Method* meth, const char* func)
137 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
138 LOGW(" in %s.%s %s (%s)\n",
139 meth->clazz->descriptor, meth->name, desc, func + 6);
144 * Abort if we are configured to bail out on JNI warnings.
146 static inline void abortMaybe()
148 JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
150 dvmDumpThread(dvmThreadSelf(), false);
156 * Verify that the current thread is (a) attached and (b) associated with
157 * this particular instance of JNIEnv.
159 * Verify that, if this thread previously made a critical "get" call, we
160 * do the corresponding "release" call before we try anything else.
162 * Verify that, if an exception has been raised, the native code doesn't
163 * make any JNI calls other than the Exception* methods.
165 * TODO? if we add support for non-JNI native calls, make sure that the
166 * method at the top of the interpreted stack is a JNI method call. (Or
167 * set a flag in the Thread/JNIEnv when the call is made and clear it on
170 * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
172 static void checkThread(JNIEnv* env, int flags, const char* func)
174 JNIEnvExt* threadEnv;
175 bool printWarn = false;
176 bool printException = false;
178 /* get the *correct* JNIEnv by going through our TLS pointer */
179 threadEnv = dvmGetJNIEnvForThread();
182 * Verify that the JNIEnv we've been handed matches what we expected
185 if (threadEnv == NULL) {
186 LOGE("JNI ERROR: non-VM thread making JNI calls\n");
187 // don't set printWarn
188 } else if ((JNIEnvExt*) env != threadEnv) {
189 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
190 LOGE("JNI: threadEnv != thread->env?\n");
194 LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
195 threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
198 /* this is a bad idea -- need to throw as we exit, or abort func */
199 //dvmThrowException("Ljava/lang/RuntimeException;",
200 // "invalid use of JNI env ptr");
201 } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
202 /* correct JNIEnv*; make sure the "self" pointer is correct */
203 LOGE("JNI: env->self != thread-self\n");
208 * Check for critical resource misuse.
210 switch (flags & kFlag_CritMask) {
211 case kFlag_CritOkay: // okay to call this method
213 case kFlag_CritBad: // not okay to call
214 if (threadEnv->critical) {
215 LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
216 threadEnv->envThreadId);
220 case kFlag_CritGet: // this is a "get" call
221 /* don't check here; we allow nested gets */
222 threadEnv->critical++;
224 case kFlag_CritRelease: // this is a "release" call
225 threadEnv->critical--;
226 if (threadEnv->critical < 0) {
227 LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
228 threadEnv->envThreadId);
237 * Check for raised exceptions.
239 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
240 LOGW("JNI WARNING: JNI method called with exception raised\n");
242 printException = true;
246 Thread* self = dvmThreadSelf();
248 (int) dvmReferenceTableEntries(&self->internalLocalRefTable));
252 showLocation(dvmGetCurrentJNIMethod(), func);
253 if (printException) {
254 LOGW("Pending exception is:\n");
255 dvmLogExceptionStackTrace();
262 * Verify that the field is of the appropriate type. If the field has an
263 * object type, "obj" is the object we're trying to assign into it.
265 * Works for both static and instance fields.
267 static void checkFieldType(jobject obj, jfieldID fieldID, PrimitiveType prim,
268 bool isStatic, const char* func)
270 static const char* primNameList[] = {
271 "Object/Array", "boolean", "char", "float", "double",
272 "byte", "short", "int", "long", "void"
274 const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
275 Field* field = (Field*) fieldID;
276 bool printWarn = false;
278 if (fieldID == NULL) {
279 LOGE("JNI ERROR: null field ID\n");
283 if (field->signature[0] == 'L' || field->signature[0] == '[') {
285 ClassObject* fieldClass =
286 dvmFindLoadedClass(field->signature);
287 ClassObject* objClass = ((Object*)obj)->clazz;
289 assert(fieldClass != NULL);
290 assert(objClass != NULL);
292 if (!dvmInstanceof(objClass, fieldClass)) {
293 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
294 field->name, field->signature, objClass->descriptor);
298 } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
299 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
300 field->name, field->signature, primNames[prim]);
302 } else if (isStatic && !dvmIsStaticField(field)) {
304 LOGW("JNI WARNING: accessing non-static field %s as static\n",
307 LOGW("JNI WARNING: accessing static field %s as non-static\n",
313 showLocation(dvmGetCurrentJNIMethod(), func);
319 * Verify that "obj" is a valid object, and that it's an object that JNI
320 * is allowed to know about. We allow NULL references.
322 * The caller should have switched to "running" mode before calling here.
324 static void checkObject(JNIEnv* env, jobject obj, const char* func)
326 UNUSED_PARAMETER(env);
327 bool printWarn = false;
331 if (!dvmIsValidObject(obj)) {
332 LOGW("JNI WARNING: native code passing in bad object %p (%s)\n",
335 } else if (dvmGetJNIRefType(obj) == JNIInvalidRefType) {
336 LOGW("JNI WARNING: ref %p should not be visible to native code\n", obj);
341 showLocation(dvmGetCurrentJNIMethod(), func);
347 * Verify that "clazz" actually points to a class object. (Also performs
350 * We probably don't need to identify where we're being called from,
351 * because the VM is most likely about to crash and leave a core dump
352 * if something is wrong.
354 * Because we're looking at an object on the GC heap, we have to switch
355 * to "running" mode before doing the checks.
357 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
360 bool printWarn = false;
362 ClassObject* clazz = (ClassObject*) jclazz;
365 LOGW("JNI WARNING: received null jclass\n");
367 } else if (!dvmIsValidObject((Object*) clazz)) {
368 LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
370 } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
371 LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
372 jclazz, clazz->descriptor);
375 checkObject(env, jclazz, func);
385 * Verify that "str" is non-NULL and points to a String object.
387 * Since we're dealing with objects, switch to "running" mode.
389 static void checkString(JNIEnv* env, jstring str, const char* func)
392 bool printWarn = false;
394 Object* obj = (Object*) str;
397 LOGW("JNI WARNING: received null jstring (%s)\n", func);
399 } else if (obj->clazz != gDvm.classJavaLangString) {
400 if (dvmIsValidObject(obj))
401 LOGW("JNI WARNING: jstring points to non-string object (%s)\n",
404 LOGW("JNI WARNING: jstring %p is bogus (%s)\n", str, func);
407 checkObject(env, str, func);
417 * Verify that "bytes" points to valid "modified UTF-8" data.
419 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
422 const char* origBytes = bytes;
426 LOGW("JNI WARNING: unexpectedly null UTF string\n");
433 while (*bytes != '\0') {
434 u1 utf8 = *(bytes++);
435 // Switch on the high four bits.
445 // Bit pattern 0xxx. No need for any extra bytes.
454 * Bit pattern 10xx or 1111, which are illegal start bytes.
455 * Note: 1111 is valid for normal UTF-8, but not the
456 * modified UTF-8 used here.
458 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
462 // Bit pattern 1110, so there are two additional bytes.
464 if ((utf8 & 0xc0) != 0x80) {
465 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
468 // Fall through to take care of the final byte.
472 // Bit pattern 110x, so there is one additional byte.
474 if ((utf8 & 0xc0) != 0x80) {
475 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
486 LOGW(" string: '%s'\n", origBytes);
487 showLocation(dvmGetCurrentJNIMethod(), func);
492 * In some circumstances the VM will screen class names, but it doesn't
493 * for class lookup. When things get bounced through a class loader, they
494 * can actually get normalized a couple of times; as a result, passing in
495 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
496 * work in some circumstances.
498 * This is incorrect and could cause strange behavior or compatibility
499 * problems, so we want to screen that out here.
501 * We expect "full-qualified" class names, like "java/lang/Thread" or
502 * "[Ljava/lang/Object;".
504 static void checkClassName(JNIEnv* env, const char* className, const char* func)
508 /* quick check for illegal chars */
510 while (*cp != '\0') {
516 // TODO: need a more rigorous check here
521 LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
526 * Verify that "array" is non-NULL and points to an Array object.
528 * Since we're dealing with objects, switch to "running" mode.
530 static void checkArray(JNIEnv* env, jarray array, const char* func)
533 bool printWarn = false;
535 Object* obj = (Object*) array;
538 LOGW("JNI WARNING: received null array (%s)\n", func);
540 } else if (obj->clazz->descriptor[0] != '[') {
541 if (dvmIsValidObject(obj))
542 LOGW("JNI WARNING: jarray points to non-array object\n");
544 LOGW("JNI WARNING: jarray is bogus (%p)\n", array);
547 checkObject(env, array, func);
557 * Verify that the "mode" argument passed to a primitive array Release
558 * function is one of the valid values.
560 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
562 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
563 LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
569 * Verify that the length argument to array-creation calls is >= 0.
571 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
574 LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
580 * Verify that the pointer value is non-NULL.
582 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
585 LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
591 * Verify that the method's return type matches the type of call.
593 * "expectedSigByte" will be 'L' for all objects, including arrays.
595 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
596 bool isStatic, const char* func)
598 const Method* meth = (const Method*) methodID;
599 bool printWarn = false;
601 if (expectedSigByte != meth->shorty[0]) {
602 LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
604 } else if (isStatic && !dvmIsStaticMethod(meth)) {
606 LOGW("JNI WARNING: calling non-static method with static call\n");
608 LOGW("JNI WARNING: calling static method with non-static call\n");
613 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
614 LOGW(" calling %s.%s %s\n",
615 meth->clazz->descriptor, meth->name, desc);
617 showLocation(dvmGetCurrentJNIMethod(), func);
623 * Verify that this static field ID is valid for this class.
625 static void checkStaticFieldID(JNIEnv* env, jclass clazz, jfieldID fieldID)
627 StaticField* base = ((ClassObject*) clazz)->sfields;
628 int fieldCount = ((ClassObject*) clazz)->sfieldCount;
630 if ((StaticField*) fieldID < base ||
631 (StaticField*) fieldID >= base + fieldCount)
633 LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
634 fieldID, ((ClassObject*) clazz)->descriptor);
635 LOGW(" base=%p count=%d\n", base, fieldCount);
641 * Verify that this instance field ID is valid for this object.
643 static void checkInstanceFieldID(JNIEnv* env, jobject obj, jfieldID fieldID,
647 LOGW("JNI WARNING: invalid null object (%s)\n", func);
652 ClassObject* clazz = ((Object*)obj)->clazz;
655 * Check this class and all of its superclasses for a matching field.
656 * Don't need to scan interfaces.
658 while (clazz != NULL) {
659 if ((InstField*) fieldID >= clazz->ifields &&
660 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
665 clazz = clazz->super;
668 LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
669 fieldID, ((Object*)obj)->clazz->descriptor);
675 * ===========================================================================
677 * ===========================================================================
680 #define kGuardLen 512 /* must be multiple of 2 */
681 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
682 #define kGuardMagic 0xffd5aa96
683 #define kGuardExtra sizeof(GuardExtra)
685 /* this gets tucked in at the start of the buffer; struct size must be even */
686 typedef struct GuardExtra {
690 const void* originalPtr;
693 /* find the GuardExtra given the pointer into the "live" data */
694 inline static GuardExtra* getGuardExtra(const void* dataBuf)
696 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
697 return (GuardExtra*) fullBuf;
701 * Create an oversized buffer to hold the contents of "buf". Copy it in,
702 * filling in the area around it with guard data.
704 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
706 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
709 size_t newLen = (len + kGuardLen +1) & ~0x01;
714 newBuf = (u1*)malloc(newLen);
715 if (newBuf == NULL) {
716 LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
720 /* fill it in with a pattern */
722 for (i = 0; i < (int)newLen / 2; i++)
723 *pat++ = kGuardPattern;
725 /* copy the data in; note "len" could be zero */
726 memcpy(newBuf + kGuardLen / 2, buf, len);
728 /* if modification is not expected, grab a checksum */
731 adler = adler32(0L, Z_NULL, 0);
732 adler = adler32(adler, buf, len);
733 *(uLong*)newBuf = adler;
736 pExtra = (GuardExtra*) newBuf;
737 pExtra->magic = kGuardMagic;
738 pExtra->adler = adler;
739 pExtra->originalPtr = buf;
740 pExtra->originalLen = len;
742 return newBuf + kGuardLen / 2;
746 * Verify the guard area and, if "modOkay" is false, that the data itself
747 * has not been altered.
749 * The caller has already checked that "dataBuf" is non-NULL.
751 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
753 static const u4 kMagicCmp = kGuardMagic;
754 const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
755 const GuardExtra* pExtra = getGuardExtra(dataBuf);
761 * Before we do anything with "pExtra", check the magic number. We
762 * do the check with memcmp rather than "==" in case the pointer is
763 * unaligned. If it points to completely bogus memory we're going
764 * to crash, but there's no easy way around that.
766 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
768 memcpy(buf, &pExtra->magic, 4);
769 LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
770 "-- incorrect data pointer %p?\n",
771 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
775 len = pExtra->originalLen;
777 /* check bottom half of guard; skip over optional checksum storage */
779 for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
781 if (pat[i] != kGuardPattern) {
782 LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
788 int offset = kGuardLen / 2 + len;
790 /* odd byte; expected value depends on endian-ness of host */
791 const u2 patSample = kGuardPattern;
792 if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
793 LOGE("JNI: guard pattern disturbed in odd byte after %p "
794 "(+%d) 0x%02x 0x%02x\n",
795 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
801 /* check top half of guard */
802 pat = (u2*) (fullBuf + offset);
803 for (i = 0; i < kGuardLen / 4; i++) {
804 if (pat[i] != kGuardPattern) {
805 LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
806 fullBuf, offset + i*2);
812 * If modification is not expected, verify checksum. Strictly speaking
813 * this is wrong: if we told the client that we made a copy, there's no
814 * reason they can't alter the buffer.
817 uLong adler = adler32(0L, Z_NULL, 0);
818 adler = adler32(adler, dataBuf, len);
819 if (pExtra->adler != adler) {
820 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
821 pExtra->adler, adler, dataBuf);
830 * Free up the guard buffer, scrub it, and return the original pointer.
832 static void* freeGuardedCopy(void* dataBuf)
834 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
835 const GuardExtra* pExtra = getGuardExtra(dataBuf);
836 void* originalPtr = (void*) pExtra->originalPtr;
837 size_t len = pExtra->originalLen;
839 memset(dataBuf, len, 0xdd);
845 * Just pull out the original pointer.
847 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
849 const GuardExtra* pExtra = getGuardExtra(dataBuf);
850 return (void*) pExtra->originalPtr;
854 * Grab the data length.
856 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
858 const GuardExtra* pExtra = getGuardExtra(dataBuf);
859 return pExtra->originalLen;
863 * Return the width, in bytes, of a primitive type.
865 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
867 static const int lengths[PRIM_MAX] = {
878 assert(primType >= 0 && primType < PRIM_MAX);
879 return lengths[primType];
883 * Create a guarded copy of a primitive array. Modifications to the copied
884 * data are allowed. Returns a pointer to the copied data.
886 static void* createGuardedPACopy(const ArrayObject* array, jboolean* isCopy)
888 PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
889 int len = array->length * dvmPrimitiveTypeWidth(primType);
892 result = createGuardedCopy(array->contents, len, true);
901 * Perform the array "release" operation, which may or may not copy data
902 * back into the VM, and may or may not release the underlying storage.
904 static void* releaseGuardedPACopy(ArrayObject* array, void* dataBuf, int mode)
906 PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
907 //int len = array->length * dvmPrimitiveTypeWidth(primType);
908 bool release, copyBack;
911 if (!checkGuardedCopy(dataBuf, true)) {
912 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
919 release = copyBack = true;
930 LOGE("JNI: bad release mode %d\n", mode);
936 size_t len = getGuardedCopyOriginalLen(dataBuf);
937 memcpy(array->contents, dataBuf, len);
941 result = (u1*) freeGuardedCopy(dataBuf);
943 result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
946 /* pointer is to the array contents; back up to the array object */
947 result -= offsetof(ArrayObject, contents);
954 * ===========================================================================
956 * ===========================================================================
959 static jint Check_GetVersion(JNIEnv* env)
961 CHECK_ENTER(env, kFlag_Default);
963 result = BASE_ENV(env)->GetVersion(env);
968 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
969 const jbyte* buf, jsize bufLen)
971 CHECK_ENTER(env, kFlag_Default);
972 CHECK_OBJECT(env, loader);
973 CHECK_UTF_STRING(env, name, false);
974 CHECK_CLASS_NAME(env, name);
976 result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
981 static jclass Check_FindClass(JNIEnv* env, const char* name)
983 CHECK_ENTER(env, kFlag_Default);
984 CHECK_UTF_STRING(env, name, false);
985 CHECK_CLASS_NAME(env, name);
987 result = BASE_ENV(env)->FindClass(env, name);
992 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
994 CHECK_ENTER(env, kFlag_Default);
995 CHECK_CLASS(env, clazz);
997 result = BASE_ENV(env)->GetSuperclass(env, clazz);
1002 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1005 CHECK_ENTER(env, kFlag_Default);
1006 CHECK_CLASS(env, clazz1);
1007 CHECK_CLASS(env, clazz2);
1009 result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1014 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1016 CHECK_ENTER(env, kFlag_Default);
1017 CHECK_OBJECT(env, method);
1019 result = BASE_ENV(env)->FromReflectedMethod(env, method);
1024 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1026 CHECK_ENTER(env, kFlag_Default);
1027 CHECK_OBJECT(env, field);
1029 result = BASE_ENV(env)->FromReflectedField(env, field);
1034 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1035 jmethodID methodID, jboolean isStatic)
1037 CHECK_ENTER(env, kFlag_Default);
1038 CHECK_CLASS(env, cls);
1040 result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1045 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1048 CHECK_ENTER(env, kFlag_Default);
1049 CHECK_CLASS(env, cls);
1051 result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1056 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1058 CHECK_ENTER(env, kFlag_Default);
1059 CHECK_OBJECT(env, obj);
1061 result = BASE_ENV(env)->Throw(env, obj);
1066 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1068 CHECK_ENTER(env, kFlag_Default);
1069 CHECK_CLASS(env, clazz);
1070 CHECK_UTF_STRING(env, message, true);
1072 result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1077 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1079 CHECK_ENTER(env, kFlag_ExcepOkay);
1081 result = BASE_ENV(env)->ExceptionOccurred(env);
1086 static void Check_ExceptionDescribe(JNIEnv* env)
1088 CHECK_ENTER(env, kFlag_ExcepOkay);
1089 BASE_ENV(env)->ExceptionDescribe(env);
1093 static void Check_ExceptionClear(JNIEnv* env)
1095 CHECK_ENTER(env, kFlag_ExcepOkay);
1096 BASE_ENV(env)->ExceptionClear(env);
1100 static void Check_FatalError(JNIEnv* env, const char* msg)
1102 CHECK_ENTER(env, kFlag_Default);
1103 CHECK_UTF_STRING(env, msg, true);
1104 BASE_ENV(env)->FatalError(env, msg);
1108 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1110 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1112 result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1117 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1119 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1120 CHECK_OBJECT(env, res);
1122 result = BASE_ENV(env)->PopLocalFrame(env, res);
1127 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1129 CHECK_ENTER(env, kFlag_Default);
1130 CHECK_OBJECT(env, obj);
1132 result = BASE_ENV(env)->NewGlobalRef(env, obj);
1137 static void Check_DeleteGlobalRef(JNIEnv* env, jobject localRef)
1139 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1140 CHECK_OBJECT(env, localRef);
1141 BASE_ENV(env)->DeleteGlobalRef(env, localRef);
1145 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1147 CHECK_ENTER(env, kFlag_Default);
1148 CHECK_OBJECT(env, ref);
1150 result = BASE_ENV(env)->NewLocalRef(env, ref);
1155 static void Check_DeleteLocalRef(JNIEnv* env, jobject globalRef)
1157 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1158 CHECK_OBJECT(env, globalRef);
1159 BASE_ENV(env)->DeleteLocalRef(env, globalRef);
1163 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1165 CHECK_ENTER(env, kFlag_Default);
1167 result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1172 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1174 CHECK_ENTER(env, kFlag_Default);
1175 CHECK_OBJECT(env, ref1);
1176 CHECK_OBJECT(env, ref2);
1178 result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1183 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1185 CHECK_ENTER(env, kFlag_Default);
1186 CHECK_CLASS(env, clazz);
1188 result = BASE_ENV(env)->AllocObject(env, clazz);
1193 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1196 CHECK_ENTER(env, kFlag_Default);
1197 CHECK_CLASS(env, clazz);
1201 va_start(args, methodID);
1202 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1208 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1211 CHECK_ENTER(env, kFlag_Default);
1212 CHECK_CLASS(env, clazz);
1214 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1218 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1221 CHECK_ENTER(env, kFlag_Default);
1222 CHECK_CLASS(env, clazz);
1224 result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1229 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1231 CHECK_ENTER(env, kFlag_Default);
1232 CHECK_OBJECT(env, obj);
1234 result = BASE_ENV(env)->GetObjectClass(env, obj);
1239 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1241 CHECK_ENTER(env, kFlag_Default);
1242 CHECK_OBJECT(env, obj);
1243 CHECK_CLASS(env, clazz);
1245 result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1250 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1253 CHECK_ENTER(env, kFlag_Default);
1254 CHECK_CLASS(env, clazz);
1255 CHECK_UTF_STRING(env, name, false);
1256 CHECK_UTF_STRING(env, sig, false);
1258 result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1263 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1264 const char* name, const char* sig)
1266 CHECK_ENTER(env, kFlag_Default);
1267 CHECK_CLASS(env, clazz);
1268 CHECK_UTF_STRING(env, name, false);
1269 CHECK_UTF_STRING(env, sig, false);
1271 result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1276 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1277 const char* name, const char* sig)
1279 CHECK_ENTER(env, kFlag_Default);
1280 CHECK_CLASS(env, clazz);
1281 CHECK_UTF_STRING(env, name, false);
1282 CHECK_UTF_STRING(env, sig, false);
1284 result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1289 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1290 const char* name, const char* sig)
1292 CHECK_ENTER(env, kFlag_Default);
1293 CHECK_CLASS(env, clazz);
1294 CHECK_UTF_STRING(env, name, false);
1295 CHECK_UTF_STRING(env, sig, false);
1297 result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1302 #define GET_STATIC_TYPE_FIELD(_ctype, _jname, _isref) \
1303 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1306 CHECK_ENTER(env, kFlag_Default); \
1307 CHECK_CLASS(env, clazz); \
1309 checkStaticFieldID(env, clazz, fieldID); \
1310 result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
1315 GET_STATIC_TYPE_FIELD(jobject, Object, true);
1316 GET_STATIC_TYPE_FIELD(jboolean, Boolean, false);
1317 GET_STATIC_TYPE_FIELD(jbyte, Byte, false);
1318 GET_STATIC_TYPE_FIELD(jchar, Char, false);
1319 GET_STATIC_TYPE_FIELD(jshort, Short, false);
1320 GET_STATIC_TYPE_FIELD(jint, Int, false);
1321 GET_STATIC_TYPE_FIELD(jlong, Long, false);
1322 GET_STATIC_TYPE_FIELD(jfloat, Float, false);
1323 GET_STATIC_TYPE_FIELD(jdouble, Double, false);
1325 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1326 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1327 jfieldID fieldID, _ctype value) \
1329 CHECK_ENTER(env, kFlag_Default); \
1330 CHECK_CLASS(env, clazz); \
1331 checkStaticFieldID(env, clazz, fieldID); \
1332 CHECK_FIELD_TYPE((jobject)(u4)value, fieldID, _ftype, true); \
1333 BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
1337 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1338 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1339 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1340 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1341 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1342 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1343 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1344 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1345 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1347 #define GET_TYPE_FIELD(_ctype, _jname, _isref) \
1348 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
1351 CHECK_ENTER(env, kFlag_Default); \
1352 CHECK_OBJECT(env, obj); \
1354 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1355 result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
1359 GET_TYPE_FIELD(jobject, Object, true);
1360 GET_TYPE_FIELD(jboolean, Boolean, false);
1361 GET_TYPE_FIELD(jbyte, Byte, false);
1362 GET_TYPE_FIELD(jchar, Char, false);
1363 GET_TYPE_FIELD(jshort, Short, false);
1364 GET_TYPE_FIELD(jint, Int, false);
1365 GET_TYPE_FIELD(jlong, Long, false);
1366 GET_TYPE_FIELD(jfloat, Float, false);
1367 GET_TYPE_FIELD(jdouble, Double, false);
1369 #define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1370 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
1371 jfieldID fieldID, _ctype value) \
1373 CHECK_ENTER(env, kFlag_Default); \
1374 CHECK_OBJECT(env, obj); \
1375 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1376 CHECK_FIELD_TYPE((jobject)(u4) value, fieldID, _ftype, false); \
1377 BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
1380 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1381 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1382 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1383 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1384 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1385 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1386 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1387 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1388 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1390 #define CALL_VIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok, \
1392 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
1393 jmethodID methodID, ...) \
1395 CHECK_ENTER(env, kFlag_Default); \
1396 CHECK_OBJECT(env, obj); \
1397 CHECK_SIG(env, methodID, _retsig, false); \
1400 va_start(args, methodID); \
1401 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1407 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1408 jmethodID methodID, va_list args) \
1410 CHECK_ENTER(env, kFlag_Default); \
1411 CHECK_OBJECT(env, obj); \
1412 CHECK_SIG(env, methodID, _retsig, false); \
1414 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1419 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1420 jmethodID methodID, jvalue* args) \
1422 CHECK_ENTER(env, kFlag_Default); \
1423 CHECK_OBJECT(env, obj); \
1424 CHECK_SIG(env, methodID, _retsig, false); \
1426 _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
1431 CALL_VIRTUAL(jobject, Object, NULL, Object* result, result=, result, 'L');
1432 CALL_VIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1433 CALL_VIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1434 CALL_VIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
1435 CALL_VIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
1436 CALL_VIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
1437 CALL_VIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
1438 CALL_VIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1439 CALL_VIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1440 CALL_VIRTUAL(void, Void, , , , , 'V');
1442 #define CALL_NONVIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn, \
1444 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
1445 jobject obj, jclass clazz, jmethodID methodID, ...) \
1447 CHECK_ENTER(env, kFlag_Default); \
1448 CHECK_CLASS(env, clazz); \
1449 CHECK_OBJECT(env, obj); \
1450 CHECK_SIG(env, methodID, _retsig, false); \
1453 va_start(args, methodID); \
1454 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1455 clazz, methodID, args); \
1460 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1461 jobject obj, jclass clazz, jmethodID methodID, va_list args) \
1463 CHECK_ENTER(env, kFlag_Default); \
1464 CHECK_CLASS(env, clazz); \
1465 CHECK_OBJECT(env, obj); \
1466 CHECK_SIG(env, methodID, _retsig, false); \
1468 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1469 clazz, methodID, args); \
1473 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1474 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
1476 CHECK_ENTER(env, kFlag_Default); \
1477 CHECK_CLASS(env, clazz); \
1478 CHECK_OBJECT(env, obj); \
1479 CHECK_SIG(env, methodID, _retsig, false); \
1481 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
1482 clazz, methodID, args); \
1486 CALL_NONVIRTUAL(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
1487 CALL_NONVIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1488 CALL_NONVIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1489 CALL_NONVIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
1490 CALL_NONVIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
1491 CALL_NONVIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
1492 CALL_NONVIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
1493 CALL_NONVIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1494 CALL_NONVIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1495 CALL_NONVIRTUAL(void, Void, , , , , 'V');
1498 #define CALL_STATIC(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok, \
1500 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
1501 jclass clazz, jmethodID methodID, ...) \
1503 CHECK_ENTER(env, kFlag_Default); \
1504 CHECK_CLASS(env, clazz); \
1505 CHECK_SIG(env, methodID, _retsig, true); \
1508 va_start(args, methodID); \
1509 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1515 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
1516 jclass clazz, jmethodID methodID, va_list args) \
1518 CHECK_ENTER(env, kFlag_Default); \
1519 CHECK_CLASS(env, clazz); \
1520 CHECK_SIG(env, methodID, _retsig, true); \
1522 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1527 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
1528 jclass clazz, jmethodID methodID, jvalue* args) \
1530 CHECK_ENTER(env, kFlag_Default); \
1531 CHECK_CLASS(env, clazz); \
1532 CHECK_SIG(env, methodID, _retsig, true); \
1534 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
1539 CALL_STATIC(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
1540 CALL_STATIC(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1541 CALL_STATIC(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1542 CALL_STATIC(jchar, Char, 0, jchar result, result=, result, 'C');
1543 CALL_STATIC(jshort, Short, 0, jshort result, result=, result, 'S');
1544 CALL_STATIC(jint, Int, 0, jint result, result=, result, 'I');
1545 CALL_STATIC(jlong, Long, 0, jlong result, result=, result, 'J');
1546 CALL_STATIC(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1547 CALL_STATIC(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1548 CALL_STATIC(void, Void, , , , , 'V');
1550 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1553 CHECK_ENTER(env, kFlag_Default);
1555 result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1560 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1562 CHECK_ENTER(env, kFlag_CritOkay);
1563 CHECK_STRING(env, string);
1565 result = BASE_ENV(env)->GetStringLength(env, string);
1570 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1573 CHECK_ENTER(env, kFlag_CritOkay);
1574 CHECK_STRING(env, string);
1575 const jchar* result;
1576 result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1577 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1578 int len = dvmStringLen(string) * 2;
1579 result = (const jchar*) createGuardedCopy(result, len, false);
1587 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1590 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1591 CHECK_STRING(env, string);
1592 CHECK_NON_NULL(env, chars);
1593 if (((JNIEnvExt*)env)->forceDataCopy) {
1594 if (!checkGuardedCopy(chars, false)) {
1595 LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1599 chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1601 BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1605 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1607 CHECK_ENTER(env, kFlag_Default);
1608 CHECK_UTF_STRING(env, bytes, true);
1610 result = BASE_ENV(env)->NewStringUTF(env, bytes);
1615 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1617 CHECK_ENTER(env, kFlag_CritOkay);
1618 CHECK_STRING(env, string);
1620 result = BASE_ENV(env)->GetStringUTFLength(env, string);
1625 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1628 CHECK_ENTER(env, kFlag_CritOkay);
1629 CHECK_STRING(env, string);
1631 result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1632 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1633 int len = dvmStringUtf8ByteLen(string) + 1;
1634 result = (const char*) createGuardedCopy(result, len, false);
1642 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1645 CHECK_ENTER(env, kFlag_ExcepOkay);
1646 CHECK_STRING(env, string);
1647 CHECK_NON_NULL(env, utf);
1648 if (((JNIEnvExt*)env)->forceDataCopy) {
1649 //int len = dvmStringUtf8ByteLen(string) + 1;
1650 if (!checkGuardedCopy(utf, false)) {
1651 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1655 utf = (const char*) freeGuardedCopy((char*)utf);
1657 BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1661 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1663 CHECK_ENTER(env, kFlag_CritOkay);
1664 CHECK_ARRAY(env, array);
1666 result = BASE_ENV(env)->GetArrayLength(env, array);
1671 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1672 jclass elementClass, jobject initialElement)
1674 CHECK_ENTER(env, kFlag_Default);
1675 CHECK_CLASS(env, elementClass);
1676 CHECK_OBJECT(env, initialElement);
1677 CHECK_LENGTH_POSITIVE(env, length);
1678 jobjectArray result;
1679 result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
1685 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
1688 CHECK_ENTER(env, kFlag_Default);
1689 CHECK_ARRAY(env, array);
1691 result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
1696 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
1697 jsize index, jobject value)
1699 CHECK_ENTER(env, kFlag_Default);
1700 CHECK_ARRAY(env, array);
1701 BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
1705 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1706 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
1708 CHECK_ENTER(env, kFlag_Default); \
1709 CHECK_LENGTH_POSITIVE(env, length); \
1711 result = BASE_ENV(env)->New##_jname##Array(env, length); \
1715 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1716 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1717 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1718 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1719 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1720 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1721 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1722 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1725 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1726 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
1727 _ctype##Array array, jboolean* isCopy) \
1729 CHECK_ENTER(env, kFlag_Default); \
1730 CHECK_ARRAY(env, array); \
1732 result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
1734 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
1735 result = (_ctype*) \
1736 createGuardedPACopy((ArrayObject*) array, isCopy); \
1742 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1743 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
1744 _ctype##Array array, _ctype* elems, jint mode) \
1746 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
1747 CHECK_ARRAY(env, array); \
1748 CHECK_NON_NULL(env, elems); \
1749 CHECK_RELEASE_MODE(env, mode); \
1750 if (((JNIEnvExt*)env)->forceDataCopy) { \
1751 elems = (_ctype*) releaseGuardedPACopy((ArrayObject*) array, \
1754 BASE_ENV(env)->Release##_jname##ArrayElements(env, \
1755 array, elems, mode); \
1759 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1760 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
1761 _ctype##Array array, jsize start, jsize len, _ctype* buf) \
1763 CHECK_ENTER(env, kFlag_Default); \
1764 CHECK_ARRAY(env, array); \
1765 BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
1770 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1771 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
1772 _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
1774 CHECK_ENTER(env, kFlag_Default); \
1775 CHECK_ARRAY(env, array); \
1776 BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
1781 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1782 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1783 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1784 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1785 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1787 /* TODO: verify primitive array type matches call type */
1788 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1789 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1790 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1791 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1792 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1793 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1794 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1795 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1797 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
1798 const JNINativeMethod* methods, jint nMethods)
1800 CHECK_ENTER(env, kFlag_Default);
1801 CHECK_CLASS(env, clazz);
1803 result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
1808 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
1810 CHECK_ENTER(env, kFlag_Default);
1811 CHECK_CLASS(env, clazz);
1813 result = BASE_ENV(env)->UnregisterNatives(env, clazz);
1818 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
1820 CHECK_ENTER(env, kFlag_Default);
1821 CHECK_OBJECT(env, obj);
1823 result = BASE_ENV(env)->MonitorEnter(env, obj);
1828 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
1830 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1831 CHECK_OBJECT(env, obj);
1833 result = BASE_ENV(env)->MonitorExit(env, obj);
1838 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
1840 CHECK_ENTER(env, kFlag_Default);
1842 result = BASE_ENV(env)->GetJavaVM(env, vm);
1847 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
1848 jsize len, jchar* buf)
1850 CHECK_ENTER(env, kFlag_CritOkay);
1851 CHECK_STRING(env, str);
1852 BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
1856 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
1857 jsize len, char* buf)
1859 CHECK_ENTER(env, kFlag_CritOkay);
1860 CHECK_STRING(env, str);
1861 BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
1865 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
1868 CHECK_ENTER(env, kFlag_CritGet);
1869 CHECK_ARRAY(env, array);
1871 result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1872 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1873 result = createGuardedPACopy((ArrayObject*) array, isCopy);
1879 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
1880 void* carray, jint mode)
1882 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
1883 CHECK_ARRAY(env, array);
1884 CHECK_NON_NULL(env, carray);
1885 CHECK_RELEASE_MODE(env, mode);
1886 if (((JNIEnvExt*)env)->forceDataCopy) {
1887 carray = releaseGuardedPACopy((ArrayObject*) array, carray, mode);
1889 BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1893 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
1896 CHECK_ENTER(env, kFlag_CritGet);
1897 CHECK_STRING(env, string);
1898 const jchar* result;
1899 result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
1900 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1901 int len = dvmStringLen(string) * 2;
1902 result = (const jchar*) createGuardedCopy(result, len, false);
1910 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
1911 const jchar* carray)
1913 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
1914 CHECK_STRING(env, string);
1915 CHECK_NON_NULL(env, carray);
1916 if (((JNIEnvExt*)env)->forceDataCopy) {
1917 if (!checkGuardedCopy(carray, false)) {
1918 LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
1922 carray = (const jchar*) freeGuardedCopy((jchar*)carray);
1924 BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
1928 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
1930 CHECK_ENTER(env, kFlag_Default);
1931 CHECK_OBJECT(env, obj);
1933 result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
1938 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
1940 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1941 CHECK_OBJECT(env, obj);
1942 BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
1946 static jboolean Check_ExceptionCheck(JNIEnv* env)
1948 CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
1950 result = BASE_ENV(env)->ExceptionCheck(env);
1955 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
1957 CHECK_ENTER(env, kFlag_Default);
1958 CHECK_OBJECT(env, obj);
1959 jobjectRefType result;
1960 result = BASE_ENV(env)->GetObjectRefType(env, obj);
1965 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
1968 CHECK_ENTER(env, kFlag_Default);
1970 if (address == NULL || capacity < 0) {
1971 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
1972 address, (long) capacity);
1976 result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
1981 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
1983 CHECK_ENTER(env, kFlag_Default);
1984 CHECK_OBJECT(env, buf);
1989 result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
1994 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
1996 CHECK_ENTER(env, kFlag_Default);
1997 CHECK_OBJECT(env, buf);
2002 result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2009 * ===========================================================================
2010 * JNI invocation functions
2011 * ===========================================================================
2014 static jint Check_DestroyJavaVM(JavaVM* vm)
2016 CHECK_VMENTER(vm, false);
2018 result = BASE_VM(vm)->DestroyJavaVM(vm);
2019 CHECK_VMEXIT(vm, false);
2023 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2026 CHECK_VMENTER(vm, false);
2028 result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2029 CHECK_VMEXIT(vm, true);
2033 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2036 CHECK_VMENTER(vm, false);
2038 result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2039 CHECK_VMEXIT(vm, true);
2043 static jint Check_DetachCurrentThread(JavaVM* vm)
2045 CHECK_VMENTER(vm, true);
2047 result = BASE_VM(vm)->DetachCurrentThread(vm);
2048 CHECK_VMEXIT(vm, false);
2052 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2054 CHECK_VMENTER(vm, true);
2056 result = BASE_VM(vm)->GetEnv(vm, env, version);
2057 CHECK_VMEXIT(vm, true);
2063 * ===========================================================================
2065 * ===========================================================================
2068 static const struct JNINativeInterface gCheckNativeInterface = {
2079 Check_FromReflectedMethod,
2080 Check_FromReflectedField,
2081 Check_ToReflectedMethod,
2083 Check_GetSuperclass,
2084 Check_IsAssignableFrom,
2086 Check_ToReflectedField,
2090 Check_ExceptionOccurred,
2091 Check_ExceptionDescribe,
2092 Check_ExceptionClear,
2095 Check_PushLocalFrame,
2096 Check_PopLocalFrame,
2099 Check_DeleteGlobalRef,
2100 Check_DeleteLocalRef,
2103 Check_EnsureLocalCapacity,
2110 Check_GetObjectClass,
2115 Check_CallObjectMethod,
2116 Check_CallObjectMethodV,
2117 Check_CallObjectMethodA,
2118 Check_CallBooleanMethod,
2119 Check_CallBooleanMethodV,
2120 Check_CallBooleanMethodA,
2121 Check_CallByteMethod,
2122 Check_CallByteMethodV,
2123 Check_CallByteMethodA,
2124 Check_CallCharMethod,
2125 Check_CallCharMethodV,
2126 Check_CallCharMethodA,
2127 Check_CallShortMethod,
2128 Check_CallShortMethodV,
2129 Check_CallShortMethodA,
2130 Check_CallIntMethod,
2131 Check_CallIntMethodV,
2132 Check_CallIntMethodA,
2133 Check_CallLongMethod,
2134 Check_CallLongMethodV,
2135 Check_CallLongMethodA,
2136 Check_CallFloatMethod,
2137 Check_CallFloatMethodV,
2138 Check_CallFloatMethodA,
2139 Check_CallDoubleMethod,
2140 Check_CallDoubleMethodV,
2141 Check_CallDoubleMethodA,
2142 Check_CallVoidMethod,
2143 Check_CallVoidMethodV,
2144 Check_CallVoidMethodA,
2146 Check_CallNonvirtualObjectMethod,
2147 Check_CallNonvirtualObjectMethodV,
2148 Check_CallNonvirtualObjectMethodA,
2149 Check_CallNonvirtualBooleanMethod,
2150 Check_CallNonvirtualBooleanMethodV,
2151 Check_CallNonvirtualBooleanMethodA,
2152 Check_CallNonvirtualByteMethod,
2153 Check_CallNonvirtualByteMethodV,
2154 Check_CallNonvirtualByteMethodA,
2155 Check_CallNonvirtualCharMethod,
2156 Check_CallNonvirtualCharMethodV,
2157 Check_CallNonvirtualCharMethodA,
2158 Check_CallNonvirtualShortMethod,
2159 Check_CallNonvirtualShortMethodV,
2160 Check_CallNonvirtualShortMethodA,
2161 Check_CallNonvirtualIntMethod,
2162 Check_CallNonvirtualIntMethodV,
2163 Check_CallNonvirtualIntMethodA,
2164 Check_CallNonvirtualLongMethod,
2165 Check_CallNonvirtualLongMethodV,
2166 Check_CallNonvirtualLongMethodA,
2167 Check_CallNonvirtualFloatMethod,
2168 Check_CallNonvirtualFloatMethodV,
2169 Check_CallNonvirtualFloatMethodA,
2170 Check_CallNonvirtualDoubleMethod,
2171 Check_CallNonvirtualDoubleMethodV,
2172 Check_CallNonvirtualDoubleMethodA,
2173 Check_CallNonvirtualVoidMethod,
2174 Check_CallNonvirtualVoidMethodV,
2175 Check_CallNonvirtualVoidMethodA,
2179 Check_GetObjectField,
2180 Check_GetBooleanField,
2183 Check_GetShortField,
2186 Check_GetFloatField,
2187 Check_GetDoubleField,
2188 Check_SetObjectField,
2189 Check_SetBooleanField,
2192 Check_SetShortField,
2195 Check_SetFloatField,
2196 Check_SetDoubleField,
2198 Check_GetStaticMethodID,
2200 Check_CallStaticObjectMethod,
2201 Check_CallStaticObjectMethodV,
2202 Check_CallStaticObjectMethodA,
2203 Check_CallStaticBooleanMethod,
2204 Check_CallStaticBooleanMethodV,
2205 Check_CallStaticBooleanMethodA,
2206 Check_CallStaticByteMethod,
2207 Check_CallStaticByteMethodV,
2208 Check_CallStaticByteMethodA,
2209 Check_CallStaticCharMethod,
2210 Check_CallStaticCharMethodV,
2211 Check_CallStaticCharMethodA,
2212 Check_CallStaticShortMethod,
2213 Check_CallStaticShortMethodV,
2214 Check_CallStaticShortMethodA,
2215 Check_CallStaticIntMethod,
2216 Check_CallStaticIntMethodV,
2217 Check_CallStaticIntMethodA,
2218 Check_CallStaticLongMethod,
2219 Check_CallStaticLongMethodV,
2220 Check_CallStaticLongMethodA,
2221 Check_CallStaticFloatMethod,
2222 Check_CallStaticFloatMethodV,
2223 Check_CallStaticFloatMethodA,
2224 Check_CallStaticDoubleMethod,
2225 Check_CallStaticDoubleMethodV,
2226 Check_CallStaticDoubleMethodA,
2227 Check_CallStaticVoidMethod,
2228 Check_CallStaticVoidMethodV,
2229 Check_CallStaticVoidMethodA,
2231 Check_GetStaticFieldID,
2233 Check_GetStaticObjectField,
2234 Check_GetStaticBooleanField,
2235 Check_GetStaticByteField,
2236 Check_GetStaticCharField,
2237 Check_GetStaticShortField,
2238 Check_GetStaticIntField,
2239 Check_GetStaticLongField,
2240 Check_GetStaticFloatField,
2241 Check_GetStaticDoubleField,
2243 Check_SetStaticObjectField,
2244 Check_SetStaticBooleanField,
2245 Check_SetStaticByteField,
2246 Check_SetStaticCharField,
2247 Check_SetStaticShortField,
2248 Check_SetStaticIntField,
2249 Check_SetStaticLongField,
2250 Check_SetStaticFloatField,
2251 Check_SetStaticDoubleField,
2255 Check_GetStringLength,
2256 Check_GetStringChars,
2257 Check_ReleaseStringChars,
2260 Check_GetStringUTFLength,
2261 Check_GetStringUTFChars,
2262 Check_ReleaseStringUTFChars,
2264 Check_GetArrayLength,
2265 Check_NewObjectArray,
2266 Check_GetObjectArrayElement,
2267 Check_SetObjectArrayElement,
2269 Check_NewBooleanArray,
2272 Check_NewShortArray,
2275 Check_NewFloatArray,
2276 Check_NewDoubleArray,
2278 Check_GetBooleanArrayElements,
2279 Check_GetByteArrayElements,
2280 Check_GetCharArrayElements,
2281 Check_GetShortArrayElements,
2282 Check_GetIntArrayElements,
2283 Check_GetLongArrayElements,
2284 Check_GetFloatArrayElements,
2285 Check_GetDoubleArrayElements,
2287 Check_ReleaseBooleanArrayElements,
2288 Check_ReleaseByteArrayElements,
2289 Check_ReleaseCharArrayElements,
2290 Check_ReleaseShortArrayElements,
2291 Check_ReleaseIntArrayElements,
2292 Check_ReleaseLongArrayElements,
2293 Check_ReleaseFloatArrayElements,
2294 Check_ReleaseDoubleArrayElements,
2296 Check_GetBooleanArrayRegion,
2297 Check_GetByteArrayRegion,
2298 Check_GetCharArrayRegion,
2299 Check_GetShortArrayRegion,
2300 Check_GetIntArrayRegion,
2301 Check_GetLongArrayRegion,
2302 Check_GetFloatArrayRegion,
2303 Check_GetDoubleArrayRegion,
2304 Check_SetBooleanArrayRegion,
2305 Check_SetByteArrayRegion,
2306 Check_SetCharArrayRegion,
2307 Check_SetShortArrayRegion,
2308 Check_SetIntArrayRegion,
2309 Check_SetLongArrayRegion,
2310 Check_SetFloatArrayRegion,
2311 Check_SetDoubleArrayRegion,
2313 Check_RegisterNatives,
2314 Check_UnregisterNatives,
2321 Check_GetStringRegion,
2322 Check_GetStringUTFRegion,
2324 Check_GetPrimitiveArrayCritical,
2325 Check_ReleasePrimitiveArrayCritical,
2327 Check_GetStringCritical,
2328 Check_ReleaseStringCritical,
2330 Check_NewWeakGlobalRef,
2331 Check_DeleteWeakGlobalRef,
2333 Check_ExceptionCheck,
2335 Check_NewDirectByteBuffer,
2336 Check_GetDirectBufferAddress,
2337 Check_GetDirectBufferCapacity,
2339 Check_GetObjectRefType
2341 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2346 Check_DestroyJavaVM,
2347 Check_AttachCurrentThread,
2348 Check_DetachCurrentThread,
2352 Check_AttachCurrentThreadAsDaemon,
2357 * Replace the normal table with the checked table.
2359 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2361 assert(pEnv->funcTable != &gCheckNativeInterface);
2362 pEnv->baseFuncTable = pEnv->funcTable;
2363 pEnv->funcTable = &gCheckNativeInterface;
2367 * Replace the normal table with the checked table.
2369 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2371 assert(pVm->funcTable != &gCheckInvokeInterface);
2372 pVm->baseFuncTable = pVm->funcTable;
2373 pVm->funcTable = &gCheckInvokeInterface;