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_CLASS(_env, _clazz) \
88 checkClass(_env, _clazz, __FUNCTION__)
89 #define CHECK_STRING(_env, _str) \
90 checkString(_env, _str, __FUNCTION__)
91 #define CHECK_UTF_STRING(_env, _str, _nullok) \
92 checkUtfString(_env, _str, _nullok, __FUNCTION__)
93 #define CHECK_CLASS_NAME(_env, _str) \
94 checkClassName(_env, _str, __FUNCTION__)
95 #define CHECK_OBJECT(_env, _obj) \
96 checkObject(_env, _obj, __FUNCTION__)
97 #define CHECK_ARRAY(_env, _array) \
98 checkArray(_env, _array, __FUNCTION__)
99 #define CHECK_RELEASE_MODE(_env, _mode) \
100 checkReleaseMode(_env, _mode, __FUNCTION__)
101 #define CHECK_LENGTH_POSITIVE(_env, _length) \
102 checkLengthPositive(_env, _length, __FUNCTION__)
103 #define CHECK_NON_NULL(_env, _ptr) \
104 checkNonNull(_env, _ptr, __FUNCTION__)
106 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic) \
107 checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
110 * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
112 #define JNI_TRACE(_entry, _hasmeth) \
114 if (gDvm.verboseJni && (_entry)) { \
115 static const char* classDescriptor = "???"; \
116 static const char* methodName = "???"; \
118 const Method* meth = dvmGetCurrentJNIMethod(); \
119 classDescriptor = meth->clazz->descriptor; \
120 methodName = meth->name; \
122 /* use +6 to drop the leading "Check_" */ \
123 LOGI("JNI: %s (from %s.%s)", \
124 (__FUNCTION__)+6, classDescriptor, methodName); \
129 * Log the current location.
131 * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
133 static void showLocation(const Method* meth, const char* func)
135 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
136 LOGW(" in %s.%s %s (%s)\n",
137 meth->clazz->descriptor, meth->name, desc, func + 6);
142 * Abort if we are configured to bail out on JNI warnings.
144 static inline void abortMaybe()
146 JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
148 dvmDumpThread(dvmThreadSelf(), false);
154 * Verify that the current thread is (a) attached and (b) associated with
155 * this particular instance of JNIEnv.
157 * Verify that, if this thread previously made a critical "get" call, we
158 * do the corresponding "release" call before we try anything else.
160 * Verify that, if an exception has been raised, the native code doesn't
161 * make any JNI calls other than the Exception* methods.
163 * TODO? if we add support for non-JNI native calls, make sure that the
164 * method at the top of the interpreted stack is a JNI method call. (Or
165 * set a flag in the Thread/JNIEnv when the call is made and clear it on
168 * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
170 static void checkThread(JNIEnv* env, int flags, const char* func)
172 JNIEnvExt* threadEnv;
173 bool printWarn = false;
174 bool printException = false;
176 /* get the *correct* JNIEnv by going through our TLS pointer */
177 threadEnv = dvmGetJNIEnvForThread();
180 * Verify that the JNIEnv we've been handed matches what we expected
183 if (threadEnv == NULL) {
184 LOGE("JNI ERROR: non-VM thread making JNI calls\n");
185 // don't set printWarn
186 } else if ((JNIEnvExt*) env != threadEnv) {
187 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
188 LOGE("JNI: threadEnv != thread->env?\n");
192 LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
193 threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
196 /* this is a bad idea -- need to throw as we exit, or abort func */
197 //dvmThrowException("Ljava/lang/RuntimeException;",
198 // "invalid use of JNI env ptr");
199 } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
200 /* correct JNIEnv*; make sure the "self" pointer is correct */
201 LOGE("JNI: env->self != thread-self\n");
206 * Check for critical resource misuse.
208 switch (flags & kFlag_CritMask) {
209 case kFlag_CritOkay: // okay to call this method
211 case kFlag_CritBad: // not okay to call
212 if (threadEnv->critical) {
213 LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
214 threadEnv->envThreadId);
218 case kFlag_CritGet: // this is a "get" call
219 /* don't check here; we allow nested gets */
220 threadEnv->critical++;
222 case kFlag_CritRelease: // this is a "release" call
223 threadEnv->critical--;
224 if (threadEnv->critical < 0) {
225 LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
226 threadEnv->envThreadId);
235 * Check for raised exceptions.
237 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
238 LOGW("JNI WARNING: JNI method called with exception raised\n");
240 printException = true;
244 Thread* self = dvmThreadSelf();
246 (int) dvmReferenceTableEntries(&self->internalLocalRefTable));
250 showLocation(dvmGetCurrentJNIMethod(), func);
251 if (printException) {
252 LOGW("Pending exception is:\n");
253 dvmLogExceptionStackTrace();
260 * Verify that the field is of the appropriate type. If the field has an
261 * object type, "obj" is the object we're trying to assign into it.
263 * Works for both static and instance fields.
265 static void checkFieldType(jobject obj, jfieldID fieldID, PrimitiveType prim,
266 bool isStatic, const char* func)
268 static const char* primNameList[] = {
269 "Object/Array", "boolean", "char", "float", "double",
270 "byte", "short", "int", "long", "void"
272 const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
273 Field* field = (Field*) fieldID;
274 bool printWarn = false;
276 if (fieldID == NULL) {
277 LOGE("JNI ERROR: null field ID\n");
281 if (field->signature[0] == 'L' || field->signature[0] == '[') {
283 ClassObject* fieldClass =
284 dvmFindLoadedClass(field->signature);
285 ClassObject* objClass = ((Object*)obj)->clazz;
287 assert(fieldClass != NULL);
288 assert(objClass != NULL);
290 if (!dvmInstanceof(objClass, fieldClass)) {
291 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
292 field->name, field->signature, objClass->descriptor);
296 } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
297 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
298 field->name, field->signature, primNames[prim]);
300 } else if (isStatic && !dvmIsStaticField(field)) {
302 LOGW("JNI WARNING: accessing non-static field %s as static\n",
305 LOGW("JNI WARNING: accessing static field %s as non-static\n",
311 showLocation(dvmGetCurrentJNIMethod(), func);
317 * Verify that "obj" is a valid object, and that it's an object that JNI
318 * is allowed to know about. We allow NULL references.
320 * The caller should have switched to "running" mode before calling here.
322 static void checkObject(JNIEnv* env, jobject obj, const char* func)
324 UNUSED_PARAMETER(env);
325 bool printWarn = false;
329 if (!dvmIsValidObject(obj)) {
330 LOGW("JNI WARNING: native code passing in bad object %p (%s)\n",
333 } else if (dvmGetJNIRefType(obj) == JNIInvalidRefType) {
334 LOGW("JNI WARNING: ref %p should not be visible to native code\n", obj);
339 showLocation(dvmGetCurrentJNIMethod(), func);
345 * Verify that "clazz" actually points to a class object. (Also performs
348 * We probably don't need to identify where we're being called from,
349 * because the VM is most likely about to crash and leave a core dump
350 * if something is wrong.
352 * Because we're looking at an object on the GC heap, we have to switch
353 * to "running" mode before doing the checks.
355 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
358 bool printWarn = false;
360 ClassObject* clazz = (ClassObject*) jclazz;
363 LOGW("JNI WARNING: received null jclass\n");
365 } else if (!dvmIsValidObject((Object*) clazz)) {
366 LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
368 } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
369 LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
370 jclazz, clazz->descriptor);
373 checkObject(env, jclazz, func);
383 * Verify that "str" is non-NULL and points to a String object.
385 * Since we're dealing with objects, switch to "running" mode.
387 static void checkString(JNIEnv* env, jstring str, const char* func)
390 bool printWarn = false;
392 Object* obj = (Object*) str;
395 LOGW("JNI WARNING: received null jstring (%s)\n", func);
397 } else if (obj->clazz != gDvm.classJavaLangString) {
398 if (dvmIsValidObject(obj))
399 LOGW("JNI WARNING: jstring points to non-string object (%s)\n",
402 LOGW("JNI WARNING: jstring %p is bogus (%s)\n", str, func);
405 checkObject(env, str, func);
415 * Verify that "bytes" points to valid "modified UTF-8" data.
417 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
420 const char* origBytes = bytes;
424 LOGW("JNI WARNING: unexpectedly null UTF string\n");
431 while (*bytes != '\0') {
432 u1 utf8 = *(bytes++);
433 // Switch on the high four bits.
443 // Bit pattern 0xxx. No need for any extra bytes.
452 * Bit pattern 10xx or 1111, which are illegal start bytes.
453 * Note: 1111 is valid for normal UTF-8, but not the
454 * modified UTF-8 used here.
456 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
460 // Bit pattern 1110, so there are two additional bytes.
462 if ((utf8 & 0xc0) != 0x80) {
463 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
466 // Fall through to take care of the final byte.
470 // Bit pattern 110x, so there is one additional byte.
472 if ((utf8 & 0xc0) != 0x80) {
473 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
484 LOGW(" string: '%s'\n", origBytes);
485 showLocation(dvmGetCurrentJNIMethod(), func);
490 * In some circumstances the VM will screen class names, but it doesn't
491 * for class lookup. When things get bounced through a class loader, they
492 * can actually get normalized a couple of times; as a result, passing in
493 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
494 * work in some circumstances.
496 * This is incorrect and could cause strange behavior or compatibility
497 * problems, so we want to screen that out here.
499 * We expect "full-qualified" class names, like "java/lang/Thread" or
500 * "[Ljava/lang/Object;".
502 static void checkClassName(JNIEnv* env, const char* className, const char* func)
506 /* quick check for illegal chars */
508 while (*cp != '\0') {
514 // TODO: need a more rigorous check here
519 LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
524 * Verify that "array" is non-NULL and points to an Array object.
526 * Since we're dealing with objects, switch to "running" mode.
528 static void checkArray(JNIEnv* env, jarray array, const char* func)
531 bool printWarn = false;
533 Object* obj = (Object*) array;
536 LOGW("JNI WARNING: received null array (%s)\n", func);
538 } else if (obj->clazz->descriptor[0] != '[') {
539 if (dvmIsValidObject(obj))
540 LOGW("JNI WARNING: jarray points to non-array object\n");
542 LOGW("JNI WARNING: jarray is bogus (%p)\n", array);
545 checkObject(env, array, func);
555 * Verify that the "mode" argument passed to a primitive array Release
556 * function is one of the valid values.
558 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
560 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
561 LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
567 * Verify that the length argument to array-creation calls is >= 0.
569 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
572 LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
578 * Verify that the pointer value is non-NULL.
580 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
583 LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
589 * Verify that the method's return type matches the type of call.
591 * "expectedSigByte" will be 'L' for all objects, including arrays.
593 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
594 bool isStatic, const char* func)
596 const Method* meth = (const Method*) methodID;
597 bool printWarn = false;
599 if (expectedSigByte != meth->shorty[0]) {
600 LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
602 } else if (isStatic && !dvmIsStaticMethod(meth)) {
604 LOGW("JNI WARNING: calling non-static method with static call\n");
606 LOGW("JNI WARNING: calling static method with non-static call\n");
611 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
612 LOGW(" calling %s.%s %s\n",
613 meth->clazz->descriptor, meth->name, desc);
615 showLocation(dvmGetCurrentJNIMethod(), func);
621 * Verify that this static field ID is valid for this class.
623 static void checkStaticFieldID(JNIEnv* env, jclass clazz, jfieldID fieldID)
625 StaticField* base = ((ClassObject*) clazz)->sfields;
626 int fieldCount = ((ClassObject*) clazz)->sfieldCount;
628 if ((StaticField*) fieldID < base ||
629 (StaticField*) fieldID >= base + fieldCount)
631 LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
632 fieldID, ((ClassObject*) clazz)->descriptor);
633 LOGW(" base=%p count=%d\n", base, fieldCount);
639 * Verify that this instance field ID is valid for this object.
641 static void checkInstanceFieldID(JNIEnv* env, jobject obj, jfieldID fieldID)
643 ClassObject* clazz = ((Object*)obj)->clazz;
646 * Check this class and all of its superclasses for a matching field.
647 * Don't need to scan interfaces.
649 while (clazz != NULL) {
650 if ((InstField*) fieldID >= clazz->ifields &&
651 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
656 clazz = clazz->super;
659 LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
660 fieldID, ((Object*)obj)->clazz->descriptor);
666 * ===========================================================================
668 * ===========================================================================
671 #define kGuardLen 512 /* must be multiple of 2 */
672 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
673 #define kGuardMagic 0xffd5aa96
674 #define kGuardExtra sizeof(GuardExtra)
676 /* this gets tucked in at the start of the buffer; struct size must be even */
677 typedef struct GuardExtra {
681 const void* originalPtr;
684 /* find the GuardExtra given the pointer into the "live" data */
685 inline static GuardExtra* getGuardExtra(const void* dataBuf)
687 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
688 return (GuardExtra*) fullBuf;
692 * Create an oversized buffer to hold the contents of "buf". Copy it in,
693 * filling in the area around it with guard data.
695 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
697 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
700 size_t newLen = (len + kGuardLen +1) & ~0x01;
705 newBuf = (u1*)malloc(newLen);
706 if (newBuf == NULL) {
707 LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
711 /* fill it in with a pattern */
713 for (i = 0; i < (int)newLen / 2; i++)
714 *pat++ = kGuardPattern;
716 /* copy the data in; note "len" could be zero */
717 memcpy(newBuf + kGuardLen / 2, buf, len);
719 /* if modification is not expected, grab a checksum */
722 adler = adler32(0L, Z_NULL, 0);
723 adler = adler32(adler, buf, len);
724 *(uLong*)newBuf = adler;
727 pExtra = (GuardExtra*) newBuf;
728 pExtra->magic = kGuardMagic;
729 pExtra->adler = adler;
730 pExtra->originalPtr = buf;
731 pExtra->originalLen = len;
733 return newBuf + kGuardLen / 2;
737 * Verify the guard area and, if "modOkay" is false, that the data itself
738 * has not been altered.
740 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
742 const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
743 const GuardExtra* pExtra = getGuardExtra(dataBuf);
744 size_t len = pExtra->originalLen;
748 if (pExtra->magic != kGuardMagic) {
749 LOGE("JNI: guard magic does not match (found 0x%08x) "
750 "-- incorrect data pointer %p?\n",
751 pExtra->magic, dataBuf);
755 /* check bottom half of guard; skip over optional checksum storage */
757 for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
759 if (pat[i] != kGuardPattern) {
760 LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
766 int offset = kGuardLen / 2 + len;
768 /* odd byte; expected value depends on endian-ness of host */
769 const u2 patSample = kGuardPattern;
770 if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
771 LOGE("JNI: guard pattern disturbed in odd byte after %p "
772 "(+%d) 0x%02x 0x%02x\n",
773 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
779 /* check top half of guard */
780 pat = (u2*) (fullBuf + offset);
781 for (i = 0; i < kGuardLen / 4; i++) {
782 if (pat[i] != kGuardPattern) {
783 LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
784 fullBuf, offset + i*2);
790 * If modification is not expected, verify checksum. Strictly speaking
791 * this is wrong: if we told the client that we made a copy, there's no
792 * reason they can't alter the buffer.
795 uLong adler = adler32(0L, Z_NULL, 0);
796 adler = adler32(adler, dataBuf, len);
797 if (pExtra->adler != adler) {
798 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
799 pExtra->adler, adler, dataBuf);
808 * Free up the guard buffer, scrub it, and return the original pointer.
810 static void* freeGuardedCopy(void* dataBuf)
812 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
813 const GuardExtra* pExtra = getGuardExtra(dataBuf);
814 void* originalPtr = (void*) pExtra->originalPtr;
815 size_t len = pExtra->originalLen;
817 memset(dataBuf, len, 0xdd);
823 * Just pull out the original pointer.
825 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
827 const GuardExtra* pExtra = getGuardExtra(dataBuf);
828 return (void*) pExtra->originalPtr;
832 * Grab the data length.
834 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
836 const GuardExtra* pExtra = getGuardExtra(dataBuf);
837 return pExtra->originalLen;
841 * Return the width, in bytes, of a primitive type.
843 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
845 static const int lengths[PRIM_MAX] = {
856 assert(primType >= 0 && primType < PRIM_MAX);
857 return lengths[primType];
861 * Create a guarded copy of a primitive array. Modifications to the copied
862 * data are allowed. Returns a pointer to the copied data.
864 static void* createGuardedPACopy(const ArrayObject* array, jboolean* isCopy)
866 PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
867 int len = array->length * dvmPrimitiveTypeWidth(primType);
870 result = createGuardedCopy(array->contents, len, true);
879 * Perform the array "release" operation, which may or may not copy data
880 * back into the VM, and may or may not release the underlying storage.
882 static void* releaseGuardedPACopy(ArrayObject* array, void* dataBuf, int mode)
884 PrimitiveType primType = array->obj.clazz->elementClass->primitiveType;
885 //int len = array->length * dvmPrimitiveTypeWidth(primType);
886 bool release, copyBack;
889 if (!checkGuardedCopy(dataBuf, true)) {
890 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
896 release = copyBack = true;
907 LOGE("JNI: bad release mode %d\n", mode);
913 size_t len = getGuardedCopyOriginalLen(dataBuf);
914 memcpy(array->contents, dataBuf, len);
918 result = (u1*) freeGuardedCopy(dataBuf);
920 result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
923 /* pointer is to the array contents; back up to the array object */
924 result -= offsetof(ArrayObject, contents);
931 * ===========================================================================
933 * ===========================================================================
936 static jint Check_GetVersion(JNIEnv* env)
938 CHECK_ENTER(env, kFlag_Default);
940 result = BASE_ENV(env)->GetVersion(env);
945 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
946 const jbyte* buf, jsize bufLen)
948 CHECK_ENTER(env, kFlag_Default);
949 CHECK_OBJECT(env, loader);
950 CHECK_UTF_STRING(env, name, false);
951 CHECK_CLASS_NAME(env, name);
953 result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
958 static jclass Check_FindClass(JNIEnv* env, const char* name)
960 CHECK_ENTER(env, kFlag_Default);
961 CHECK_UTF_STRING(env, name, false);
962 CHECK_CLASS_NAME(env, name);
964 result = BASE_ENV(env)->FindClass(env, name);
969 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
971 CHECK_ENTER(env, kFlag_Default);
972 CHECK_CLASS(env, clazz);
974 result = BASE_ENV(env)->GetSuperclass(env, clazz);
979 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
982 CHECK_ENTER(env, kFlag_Default);
983 CHECK_CLASS(env, clazz1);
984 CHECK_CLASS(env, clazz2);
986 result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
991 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
993 CHECK_ENTER(env, kFlag_Default);
994 CHECK_OBJECT(env, method);
996 result = BASE_ENV(env)->FromReflectedMethod(env, method);
1001 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1003 CHECK_ENTER(env, kFlag_Default);
1004 CHECK_OBJECT(env, field);
1006 result = BASE_ENV(env)->FromReflectedField(env, field);
1011 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1012 jmethodID methodID, jboolean isStatic)
1014 CHECK_ENTER(env, kFlag_Default);
1015 CHECK_CLASS(env, cls);
1017 result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1022 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1025 CHECK_ENTER(env, kFlag_Default);
1026 CHECK_CLASS(env, cls);
1028 result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1033 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1035 CHECK_ENTER(env, kFlag_Default);
1036 CHECK_OBJECT(env, obj);
1038 result = BASE_ENV(env)->Throw(env, obj);
1043 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1045 CHECK_ENTER(env, kFlag_Default);
1046 CHECK_CLASS(env, clazz);
1047 CHECK_UTF_STRING(env, message, true);
1049 result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1054 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1056 CHECK_ENTER(env, kFlag_ExcepOkay);
1058 result = BASE_ENV(env)->ExceptionOccurred(env);
1063 static void Check_ExceptionDescribe(JNIEnv* env)
1065 CHECK_ENTER(env, kFlag_ExcepOkay);
1066 BASE_ENV(env)->ExceptionDescribe(env);
1070 static void Check_ExceptionClear(JNIEnv* env)
1072 CHECK_ENTER(env, kFlag_ExcepOkay);
1073 BASE_ENV(env)->ExceptionClear(env);
1077 static void Check_FatalError(JNIEnv* env, const char* msg)
1079 CHECK_ENTER(env, kFlag_Default);
1080 CHECK_UTF_STRING(env, msg, true);
1081 BASE_ENV(env)->FatalError(env, msg);
1085 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1087 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1089 result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1094 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1096 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1097 CHECK_OBJECT(env, res);
1099 result = BASE_ENV(env)->PopLocalFrame(env, res);
1104 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1106 CHECK_ENTER(env, kFlag_Default);
1107 CHECK_OBJECT(env, obj);
1109 result = BASE_ENV(env)->NewGlobalRef(env, obj);
1114 static void Check_DeleteGlobalRef(JNIEnv* env, jobject localRef)
1116 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1117 CHECK_OBJECT(env, localRef);
1118 BASE_ENV(env)->DeleteGlobalRef(env, localRef);
1122 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1124 CHECK_ENTER(env, kFlag_Default);
1125 CHECK_OBJECT(env, ref);
1127 result = BASE_ENV(env)->NewLocalRef(env, ref);
1132 static void Check_DeleteLocalRef(JNIEnv* env, jobject globalRef)
1134 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1135 CHECK_OBJECT(env, globalRef);
1136 BASE_ENV(env)->DeleteLocalRef(env, globalRef);
1140 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1142 CHECK_ENTER(env, kFlag_Default);
1144 result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1149 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1151 CHECK_ENTER(env, kFlag_Default);
1152 CHECK_OBJECT(env, ref1);
1153 CHECK_OBJECT(env, ref2);
1155 result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1160 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1162 CHECK_ENTER(env, kFlag_Default);
1163 CHECK_CLASS(env, clazz);
1165 result = BASE_ENV(env)->AllocObject(env, clazz);
1170 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1173 CHECK_ENTER(env, kFlag_Default);
1174 CHECK_CLASS(env, clazz);
1178 va_start(args, methodID);
1179 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1185 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1188 CHECK_ENTER(env, kFlag_Default);
1189 CHECK_CLASS(env, clazz);
1191 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1195 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1198 CHECK_ENTER(env, kFlag_Default);
1199 CHECK_CLASS(env, clazz);
1201 result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1206 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1208 CHECK_ENTER(env, kFlag_Default);
1209 CHECK_OBJECT(env, obj);
1211 result = BASE_ENV(env)->GetObjectClass(env, obj);
1216 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1218 CHECK_ENTER(env, kFlag_Default);
1219 CHECK_OBJECT(env, obj);
1220 CHECK_CLASS(env, clazz);
1222 result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1227 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1230 CHECK_ENTER(env, kFlag_Default);
1231 CHECK_CLASS(env, clazz);
1232 CHECK_UTF_STRING(env, name, false);
1233 CHECK_UTF_STRING(env, sig, false);
1235 result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1240 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1241 const char* name, const char* sig)
1243 CHECK_ENTER(env, kFlag_Default);
1244 CHECK_CLASS(env, clazz);
1245 CHECK_UTF_STRING(env, name, false);
1246 CHECK_UTF_STRING(env, sig, false);
1248 result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1253 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1254 const char* name, const char* sig)
1256 CHECK_ENTER(env, kFlag_Default);
1257 CHECK_CLASS(env, clazz);
1258 CHECK_UTF_STRING(env, name, false);
1259 CHECK_UTF_STRING(env, sig, false);
1261 result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1266 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1267 const char* name, const char* sig)
1269 CHECK_ENTER(env, kFlag_Default);
1270 CHECK_CLASS(env, clazz);
1271 CHECK_UTF_STRING(env, name, false);
1272 CHECK_UTF_STRING(env, sig, false);
1274 result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1279 #define GET_STATIC_TYPE_FIELD(_ctype, _jname, _isref) \
1280 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1283 CHECK_ENTER(env, kFlag_Default); \
1284 CHECK_CLASS(env, clazz); \
1286 checkStaticFieldID(env, clazz, fieldID); \
1287 result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
1292 GET_STATIC_TYPE_FIELD(jobject, Object, true);
1293 GET_STATIC_TYPE_FIELD(jboolean, Boolean, false);
1294 GET_STATIC_TYPE_FIELD(jbyte, Byte, false);
1295 GET_STATIC_TYPE_FIELD(jchar, Char, false);
1296 GET_STATIC_TYPE_FIELD(jshort, Short, false);
1297 GET_STATIC_TYPE_FIELD(jint, Int, false);
1298 GET_STATIC_TYPE_FIELD(jlong, Long, false);
1299 GET_STATIC_TYPE_FIELD(jfloat, Float, false);
1300 GET_STATIC_TYPE_FIELD(jdouble, Double, false);
1302 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1303 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1304 jfieldID fieldID, _ctype value) \
1306 CHECK_ENTER(env, kFlag_Default); \
1307 CHECK_CLASS(env, clazz); \
1308 checkStaticFieldID(env, clazz, fieldID); \
1309 CHECK_FIELD_TYPE((jobject)(u4)value, fieldID, _ftype, true); \
1310 BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
1314 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1315 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1316 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1317 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1318 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1319 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1320 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1321 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1322 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1324 #define GET_TYPE_FIELD(_ctype, _jname, _isref) \
1325 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
1328 CHECK_ENTER(env, kFlag_Default); \
1329 CHECK_OBJECT(env, obj); \
1331 checkInstanceFieldID(env, obj, fieldID); \
1332 result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
1336 GET_TYPE_FIELD(jobject, Object, true);
1337 GET_TYPE_FIELD(jboolean, Boolean, false);
1338 GET_TYPE_FIELD(jbyte, Byte, false);
1339 GET_TYPE_FIELD(jchar, Char, false);
1340 GET_TYPE_FIELD(jshort, Short, false);
1341 GET_TYPE_FIELD(jint, Int, false);
1342 GET_TYPE_FIELD(jlong, Long, false);
1343 GET_TYPE_FIELD(jfloat, Float, false);
1344 GET_TYPE_FIELD(jdouble, Double, false);
1346 #define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1347 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
1348 jfieldID fieldID, _ctype value) \
1350 CHECK_ENTER(env, kFlag_Default); \
1351 CHECK_OBJECT(env, obj); \
1352 checkInstanceFieldID(env, obj, fieldID); \
1353 CHECK_FIELD_TYPE((jobject)(u4) value, fieldID, _ftype, false); \
1354 BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
1357 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1358 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1359 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1360 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1361 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1362 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1363 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1364 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1365 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1367 #define CALL_VIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok, \
1369 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
1370 jmethodID methodID, ...) \
1372 CHECK_ENTER(env, kFlag_Default); \
1373 CHECK_OBJECT(env, obj); \
1374 CHECK_SIG(env, methodID, _retsig, false); \
1377 va_start(args, methodID); \
1378 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1384 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1385 jmethodID methodID, va_list args) \
1387 CHECK_ENTER(env, kFlag_Default); \
1388 CHECK_OBJECT(env, obj); \
1389 CHECK_SIG(env, methodID, _retsig, false); \
1391 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1396 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1397 jmethodID methodID, jvalue* args) \
1399 CHECK_ENTER(env, kFlag_Default); \
1400 CHECK_OBJECT(env, obj); \
1401 CHECK_SIG(env, methodID, _retsig, false); \
1403 _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
1408 CALL_VIRTUAL(jobject, Object, NULL, Object* result, result=, result, 'L');
1409 CALL_VIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1410 CALL_VIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1411 CALL_VIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
1412 CALL_VIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
1413 CALL_VIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
1414 CALL_VIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
1415 CALL_VIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1416 CALL_VIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1417 CALL_VIRTUAL(void, Void, , , , , 'V');
1419 #define CALL_NONVIRTUAL(_ctype, _jname, _retfail, _retdecl, _retasgn, \
1421 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
1422 jobject obj, jclass clazz, jmethodID methodID, ...) \
1424 CHECK_ENTER(env, kFlag_Default); \
1425 CHECK_CLASS(env, clazz); \
1426 CHECK_OBJECT(env, obj); \
1427 CHECK_SIG(env, methodID, _retsig, false); \
1430 va_start(args, methodID); \
1431 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1432 clazz, methodID, args); \
1437 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1438 jobject obj, jclass clazz, jmethodID methodID, va_list args) \
1440 CHECK_ENTER(env, kFlag_Default); \
1441 CHECK_CLASS(env, clazz); \
1442 CHECK_OBJECT(env, obj); \
1443 CHECK_SIG(env, methodID, _retsig, false); \
1445 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1446 clazz, methodID, args); \
1450 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1451 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
1453 CHECK_ENTER(env, kFlag_Default); \
1454 CHECK_CLASS(env, clazz); \
1455 CHECK_OBJECT(env, obj); \
1456 CHECK_SIG(env, methodID, _retsig, false); \
1458 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
1459 clazz, methodID, args); \
1463 CALL_NONVIRTUAL(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
1464 CALL_NONVIRTUAL(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1465 CALL_NONVIRTUAL(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1466 CALL_NONVIRTUAL(jchar, Char, 0, jchar result, result=, result, 'C');
1467 CALL_NONVIRTUAL(jshort, Short, 0, jshort result, result=, result, 'S');
1468 CALL_NONVIRTUAL(jint, Int, 0, jint result, result=, result, 'I');
1469 CALL_NONVIRTUAL(jlong, Long, 0, jlong result, result=, result, 'J');
1470 CALL_NONVIRTUAL(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1471 CALL_NONVIRTUAL(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1472 CALL_NONVIRTUAL(void, Void, , , , , 'V');
1475 #define CALL_STATIC(_ctype, _jname, _retfail, _retdecl, _retasgn, _retok, \
1477 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
1478 jclass clazz, jmethodID methodID, ...) \
1480 CHECK_ENTER(env, kFlag_Default); \
1481 CHECK_CLASS(env, clazz); \
1482 CHECK_SIG(env, methodID, _retsig, true); \
1485 va_start(args, methodID); \
1486 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1492 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
1493 jclass clazz, jmethodID methodID, va_list args) \
1495 CHECK_ENTER(env, kFlag_Default); \
1496 CHECK_CLASS(env, clazz); \
1497 CHECK_SIG(env, methodID, _retsig, true); \
1499 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1504 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
1505 jclass clazz, jmethodID methodID, jvalue* args) \
1507 CHECK_ENTER(env, kFlag_Default); \
1508 CHECK_CLASS(env, clazz); \
1509 CHECK_SIG(env, methodID, _retsig, true); \
1511 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
1516 CALL_STATIC(jobject, Object, NULL, Object* result, result=, (Object*)(u4)result, 'L');
1517 CALL_STATIC(jboolean, Boolean, 0, jboolean result, result=, result, 'Z');
1518 CALL_STATIC(jbyte, Byte, 0, jbyte result, result=, result, 'B');
1519 CALL_STATIC(jchar, Char, 0, jchar result, result=, result, 'C');
1520 CALL_STATIC(jshort, Short, 0, jshort result, result=, result, 'S');
1521 CALL_STATIC(jint, Int, 0, jint result, result=, result, 'I');
1522 CALL_STATIC(jlong, Long, 0, jlong result, result=, result, 'J');
1523 CALL_STATIC(jfloat, Float, 0.0f, jfloat result, result=, *(float*)&result, 'F');
1524 CALL_STATIC(jdouble, Double, 0.0, jdouble result, result=, *(double*)&result, 'D');
1525 CALL_STATIC(void, Void, , , , , 'V');
1527 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1530 CHECK_ENTER(env, kFlag_Default);
1532 result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1537 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1539 CHECK_ENTER(env, kFlag_CritOkay);
1540 CHECK_STRING(env, string);
1542 result = BASE_ENV(env)->GetStringLength(env, string);
1547 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1550 CHECK_ENTER(env, kFlag_CritOkay);
1551 CHECK_STRING(env, string);
1552 const jchar* result;
1553 result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1554 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1555 int len = dvmStringLen(string) * 2;
1556 result = (const jchar*) createGuardedCopy(result, len, false);
1564 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1567 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1568 CHECK_STRING(env, string);
1569 CHECK_NON_NULL(env, chars);
1570 if (((JNIEnvExt*)env)->forceDataCopy) {
1571 if (!checkGuardedCopy(chars, false)) {
1572 LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1575 chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1577 BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1581 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1583 CHECK_ENTER(env, kFlag_Default);
1584 CHECK_UTF_STRING(env, bytes, true);
1586 result = BASE_ENV(env)->NewStringUTF(env, bytes);
1591 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1593 CHECK_ENTER(env, kFlag_CritOkay);
1594 CHECK_STRING(env, string);
1596 result = BASE_ENV(env)->GetStringUTFLength(env, string);
1601 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1604 CHECK_ENTER(env, kFlag_CritOkay);
1605 CHECK_STRING(env, string);
1607 result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1608 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1609 int len = dvmStringUtf8ByteLen(string) + 1;
1610 result = (const char*) createGuardedCopy(result, len, false);
1618 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1621 CHECK_ENTER(env, kFlag_ExcepOkay);
1622 CHECK_STRING(env, string);
1623 CHECK_NON_NULL(env, utf);
1624 if (((JNIEnvExt*)env)->forceDataCopy) {
1625 //int len = dvmStringUtf8ByteLen(string) + 1;
1626 if (!checkGuardedCopy(utf, false)) {
1627 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1630 utf = (const char*) freeGuardedCopy((char*)utf);
1632 BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1636 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1638 CHECK_ENTER(env, kFlag_CritOkay);
1639 CHECK_ARRAY(env, array);
1641 result = BASE_ENV(env)->GetArrayLength(env, array);
1646 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1647 jclass elementClass, jobject initialElement)
1649 CHECK_ENTER(env, kFlag_Default);
1650 CHECK_CLASS(env, elementClass);
1651 CHECK_OBJECT(env, initialElement);
1652 CHECK_LENGTH_POSITIVE(env, length);
1653 jobjectArray result;
1654 result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
1660 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
1663 CHECK_ENTER(env, kFlag_Default);
1664 CHECK_ARRAY(env, array);
1666 result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
1671 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
1672 jsize index, jobject value)
1674 CHECK_ENTER(env, kFlag_Default);
1675 CHECK_ARRAY(env, array);
1676 BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
1680 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1681 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
1683 CHECK_ENTER(env, kFlag_Default); \
1684 CHECK_LENGTH_POSITIVE(env, length); \
1686 result = BASE_ENV(env)->New##_jname##Array(env, length); \
1690 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1691 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1692 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1693 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1694 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1695 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1696 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1697 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1700 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1701 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
1702 _ctype##Array array, jboolean* isCopy) \
1704 CHECK_ENTER(env, kFlag_Default); \
1705 CHECK_ARRAY(env, array); \
1707 result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
1709 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
1710 result = (_ctype*) \
1711 createGuardedPACopy((ArrayObject*) array, isCopy); \
1717 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1718 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
1719 _ctype##Array array, _ctype* elems, jint mode) \
1721 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
1722 CHECK_ARRAY(env, array); \
1723 CHECK_NON_NULL(env, elems); \
1724 CHECK_RELEASE_MODE(env, mode); \
1725 if (((JNIEnvExt*)env)->forceDataCopy) { \
1726 elems = (_ctype*) releaseGuardedPACopy((ArrayObject*) array, \
1729 BASE_ENV(env)->Release##_jname##ArrayElements(env, \
1730 array, elems, mode); \
1734 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1735 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
1736 _ctype##Array array, jsize start, jsize len, _ctype* buf) \
1738 CHECK_ENTER(env, kFlag_Default); \
1739 CHECK_ARRAY(env, array); \
1740 BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
1745 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1746 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
1747 _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
1749 CHECK_ENTER(env, kFlag_Default); \
1750 CHECK_ARRAY(env, array); \
1751 BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
1756 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1757 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1758 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1759 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1760 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1762 /* TODO: verify primitive array type matches call type */
1763 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1764 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1765 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1766 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1767 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1768 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1769 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1770 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1772 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
1773 const JNINativeMethod* methods, jint nMethods)
1775 CHECK_ENTER(env, kFlag_Default);
1776 CHECK_CLASS(env, clazz);
1778 result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
1783 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
1785 CHECK_ENTER(env, kFlag_Default);
1786 CHECK_CLASS(env, clazz);
1788 result = BASE_ENV(env)->UnregisterNatives(env, clazz);
1793 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
1795 CHECK_ENTER(env, kFlag_Default);
1796 CHECK_OBJECT(env, obj);
1798 result = BASE_ENV(env)->MonitorEnter(env, obj);
1803 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
1805 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1806 CHECK_OBJECT(env, obj);
1808 result = BASE_ENV(env)->MonitorExit(env, obj);
1813 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
1815 CHECK_ENTER(env, kFlag_Default);
1817 result = BASE_ENV(env)->GetJavaVM(env, vm);
1822 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
1823 jsize len, jchar* buf)
1825 CHECK_ENTER(env, kFlag_CritOkay);
1826 CHECK_STRING(env, str);
1827 BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
1831 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
1832 jsize len, char* buf)
1834 CHECK_ENTER(env, kFlag_CritOkay);
1835 CHECK_STRING(env, str);
1836 BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
1840 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
1843 CHECK_ENTER(env, kFlag_CritGet);
1844 CHECK_ARRAY(env, array);
1846 result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
1847 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1848 result = createGuardedPACopy((ArrayObject*) array, isCopy);
1854 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
1855 void* carray, jint mode)
1857 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
1858 CHECK_ARRAY(env, array);
1859 CHECK_NON_NULL(env, carray);
1860 CHECK_RELEASE_MODE(env, mode);
1861 if (((JNIEnvExt*)env)->forceDataCopy) {
1862 carray = releaseGuardedPACopy((ArrayObject*) array, carray, mode);
1864 BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
1868 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
1871 CHECK_ENTER(env, kFlag_CritGet);
1872 CHECK_STRING(env, string);
1873 const jchar* result;
1874 result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
1875 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1876 int len = dvmStringLen(string) * 2;
1877 result = (const jchar*) createGuardedCopy(result, len, false);
1885 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
1886 const jchar* carray)
1888 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
1889 CHECK_STRING(env, string);
1890 CHECK_NON_NULL(env, carray);
1891 if (((JNIEnvExt*)env)->forceDataCopy) {
1892 if (!checkGuardedCopy(carray, false)) {
1893 LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
1896 carray = (const jchar*) freeGuardedCopy((jchar*)carray);
1898 BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
1902 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
1904 CHECK_ENTER(env, kFlag_Default);
1905 CHECK_OBJECT(env, obj);
1907 result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
1912 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
1914 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1915 CHECK_OBJECT(env, obj);
1916 BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
1920 static jboolean Check_ExceptionCheck(JNIEnv* env)
1922 CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
1924 result = BASE_ENV(env)->ExceptionCheck(env);
1929 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
1931 CHECK_ENTER(env, kFlag_Default);
1932 CHECK_OBJECT(env, obj);
1933 jobjectRefType result;
1934 result = BASE_ENV(env)->GetObjectRefType(env, obj);
1939 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
1942 CHECK_ENTER(env, kFlag_Default);
1944 if (address == NULL || capacity < 0) {
1945 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
1946 address, (long) capacity);
1949 result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
1954 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
1956 CHECK_ENTER(env, kFlag_Default);
1957 CHECK_OBJECT(env, buf);
1962 result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
1967 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
1969 CHECK_ENTER(env, kFlag_Default);
1970 CHECK_OBJECT(env, buf);
1975 result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
1982 * ===========================================================================
1983 * JNI invocation functions
1984 * ===========================================================================
1987 static jint Check_DestroyJavaVM(JavaVM* vm)
1989 CHECK_VMENTER(vm, false);
1991 result = BASE_VM(vm)->DestroyJavaVM(vm);
1992 CHECK_VMEXIT(vm, false);
1996 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
1999 CHECK_VMENTER(vm, false);
2001 result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2002 CHECK_VMEXIT(vm, true);
2006 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2009 CHECK_VMENTER(vm, false);
2011 result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2012 CHECK_VMEXIT(vm, true);
2016 static jint Check_DetachCurrentThread(JavaVM* vm)
2018 CHECK_VMENTER(vm, true);
2020 result = BASE_VM(vm)->DetachCurrentThread(vm);
2021 CHECK_VMEXIT(vm, false);
2025 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2027 CHECK_VMENTER(vm, true);
2029 result = BASE_VM(vm)->GetEnv(vm, env, version);
2030 CHECK_VMEXIT(vm, true);
2036 * ===========================================================================
2038 * ===========================================================================
2041 static const struct JNINativeInterface gCheckNativeInterface = {
2052 Check_FromReflectedMethod,
2053 Check_FromReflectedField,
2054 Check_ToReflectedMethod,
2056 Check_GetSuperclass,
2057 Check_IsAssignableFrom,
2059 Check_ToReflectedField,
2063 Check_ExceptionOccurred,
2064 Check_ExceptionDescribe,
2065 Check_ExceptionClear,
2068 Check_PushLocalFrame,
2069 Check_PopLocalFrame,
2072 Check_DeleteGlobalRef,
2073 Check_DeleteLocalRef,
2076 Check_EnsureLocalCapacity,
2083 Check_GetObjectClass,
2088 Check_CallObjectMethod,
2089 Check_CallObjectMethodV,
2090 Check_CallObjectMethodA,
2091 Check_CallBooleanMethod,
2092 Check_CallBooleanMethodV,
2093 Check_CallBooleanMethodA,
2094 Check_CallByteMethod,
2095 Check_CallByteMethodV,
2096 Check_CallByteMethodA,
2097 Check_CallCharMethod,
2098 Check_CallCharMethodV,
2099 Check_CallCharMethodA,
2100 Check_CallShortMethod,
2101 Check_CallShortMethodV,
2102 Check_CallShortMethodA,
2103 Check_CallIntMethod,
2104 Check_CallIntMethodV,
2105 Check_CallIntMethodA,
2106 Check_CallLongMethod,
2107 Check_CallLongMethodV,
2108 Check_CallLongMethodA,
2109 Check_CallFloatMethod,
2110 Check_CallFloatMethodV,
2111 Check_CallFloatMethodA,
2112 Check_CallDoubleMethod,
2113 Check_CallDoubleMethodV,
2114 Check_CallDoubleMethodA,
2115 Check_CallVoidMethod,
2116 Check_CallVoidMethodV,
2117 Check_CallVoidMethodA,
2119 Check_CallNonvirtualObjectMethod,
2120 Check_CallNonvirtualObjectMethodV,
2121 Check_CallNonvirtualObjectMethodA,
2122 Check_CallNonvirtualBooleanMethod,
2123 Check_CallNonvirtualBooleanMethodV,
2124 Check_CallNonvirtualBooleanMethodA,
2125 Check_CallNonvirtualByteMethod,
2126 Check_CallNonvirtualByteMethodV,
2127 Check_CallNonvirtualByteMethodA,
2128 Check_CallNonvirtualCharMethod,
2129 Check_CallNonvirtualCharMethodV,
2130 Check_CallNonvirtualCharMethodA,
2131 Check_CallNonvirtualShortMethod,
2132 Check_CallNonvirtualShortMethodV,
2133 Check_CallNonvirtualShortMethodA,
2134 Check_CallNonvirtualIntMethod,
2135 Check_CallNonvirtualIntMethodV,
2136 Check_CallNonvirtualIntMethodA,
2137 Check_CallNonvirtualLongMethod,
2138 Check_CallNonvirtualLongMethodV,
2139 Check_CallNonvirtualLongMethodA,
2140 Check_CallNonvirtualFloatMethod,
2141 Check_CallNonvirtualFloatMethodV,
2142 Check_CallNonvirtualFloatMethodA,
2143 Check_CallNonvirtualDoubleMethod,
2144 Check_CallNonvirtualDoubleMethodV,
2145 Check_CallNonvirtualDoubleMethodA,
2146 Check_CallNonvirtualVoidMethod,
2147 Check_CallNonvirtualVoidMethodV,
2148 Check_CallNonvirtualVoidMethodA,
2152 Check_GetObjectField,
2153 Check_GetBooleanField,
2156 Check_GetShortField,
2159 Check_GetFloatField,
2160 Check_GetDoubleField,
2161 Check_SetObjectField,
2162 Check_SetBooleanField,
2165 Check_SetShortField,
2168 Check_SetFloatField,
2169 Check_SetDoubleField,
2171 Check_GetStaticMethodID,
2173 Check_CallStaticObjectMethod,
2174 Check_CallStaticObjectMethodV,
2175 Check_CallStaticObjectMethodA,
2176 Check_CallStaticBooleanMethod,
2177 Check_CallStaticBooleanMethodV,
2178 Check_CallStaticBooleanMethodA,
2179 Check_CallStaticByteMethod,
2180 Check_CallStaticByteMethodV,
2181 Check_CallStaticByteMethodA,
2182 Check_CallStaticCharMethod,
2183 Check_CallStaticCharMethodV,
2184 Check_CallStaticCharMethodA,
2185 Check_CallStaticShortMethod,
2186 Check_CallStaticShortMethodV,
2187 Check_CallStaticShortMethodA,
2188 Check_CallStaticIntMethod,
2189 Check_CallStaticIntMethodV,
2190 Check_CallStaticIntMethodA,
2191 Check_CallStaticLongMethod,
2192 Check_CallStaticLongMethodV,
2193 Check_CallStaticLongMethodA,
2194 Check_CallStaticFloatMethod,
2195 Check_CallStaticFloatMethodV,
2196 Check_CallStaticFloatMethodA,
2197 Check_CallStaticDoubleMethod,
2198 Check_CallStaticDoubleMethodV,
2199 Check_CallStaticDoubleMethodA,
2200 Check_CallStaticVoidMethod,
2201 Check_CallStaticVoidMethodV,
2202 Check_CallStaticVoidMethodA,
2204 Check_GetStaticFieldID,
2206 Check_GetStaticObjectField,
2207 Check_GetStaticBooleanField,
2208 Check_GetStaticByteField,
2209 Check_GetStaticCharField,
2210 Check_GetStaticShortField,
2211 Check_GetStaticIntField,
2212 Check_GetStaticLongField,
2213 Check_GetStaticFloatField,
2214 Check_GetStaticDoubleField,
2216 Check_SetStaticObjectField,
2217 Check_SetStaticBooleanField,
2218 Check_SetStaticByteField,
2219 Check_SetStaticCharField,
2220 Check_SetStaticShortField,
2221 Check_SetStaticIntField,
2222 Check_SetStaticLongField,
2223 Check_SetStaticFloatField,
2224 Check_SetStaticDoubleField,
2228 Check_GetStringLength,
2229 Check_GetStringChars,
2230 Check_ReleaseStringChars,
2233 Check_GetStringUTFLength,
2234 Check_GetStringUTFChars,
2235 Check_ReleaseStringUTFChars,
2237 Check_GetArrayLength,
2238 Check_NewObjectArray,
2239 Check_GetObjectArrayElement,
2240 Check_SetObjectArrayElement,
2242 Check_NewBooleanArray,
2245 Check_NewShortArray,
2248 Check_NewFloatArray,
2249 Check_NewDoubleArray,
2251 Check_GetBooleanArrayElements,
2252 Check_GetByteArrayElements,
2253 Check_GetCharArrayElements,
2254 Check_GetShortArrayElements,
2255 Check_GetIntArrayElements,
2256 Check_GetLongArrayElements,
2257 Check_GetFloatArrayElements,
2258 Check_GetDoubleArrayElements,
2260 Check_ReleaseBooleanArrayElements,
2261 Check_ReleaseByteArrayElements,
2262 Check_ReleaseCharArrayElements,
2263 Check_ReleaseShortArrayElements,
2264 Check_ReleaseIntArrayElements,
2265 Check_ReleaseLongArrayElements,
2266 Check_ReleaseFloatArrayElements,
2267 Check_ReleaseDoubleArrayElements,
2269 Check_GetBooleanArrayRegion,
2270 Check_GetByteArrayRegion,
2271 Check_GetCharArrayRegion,
2272 Check_GetShortArrayRegion,
2273 Check_GetIntArrayRegion,
2274 Check_GetLongArrayRegion,
2275 Check_GetFloatArrayRegion,
2276 Check_GetDoubleArrayRegion,
2277 Check_SetBooleanArrayRegion,
2278 Check_SetByteArrayRegion,
2279 Check_SetCharArrayRegion,
2280 Check_SetShortArrayRegion,
2281 Check_SetIntArrayRegion,
2282 Check_SetLongArrayRegion,
2283 Check_SetFloatArrayRegion,
2284 Check_SetDoubleArrayRegion,
2286 Check_RegisterNatives,
2287 Check_UnregisterNatives,
2294 Check_GetStringRegion,
2295 Check_GetStringUTFRegion,
2297 Check_GetPrimitiveArrayCritical,
2298 Check_ReleasePrimitiveArrayCritical,
2300 Check_GetStringCritical,
2301 Check_ReleaseStringCritical,
2303 Check_NewWeakGlobalRef,
2304 Check_DeleteWeakGlobalRef,
2306 Check_ExceptionCheck,
2308 Check_NewDirectByteBuffer,
2309 Check_GetDirectBufferAddress,
2310 Check_GetDirectBufferCapacity,
2312 Check_GetObjectRefType
2314 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2319 Check_DestroyJavaVM,
2320 Check_AttachCurrentThread,
2321 Check_DetachCurrentThread,
2325 Check_AttachCurrentThreadAsDaemon,
2330 * Replace the normal table with the checked table.
2332 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2334 assert(pEnv->funcTable != &gCheckNativeInterface);
2335 pEnv->baseFuncTable = pEnv->funcTable;
2336 pEnv->funcTable = &gCheckNativeInterface;
2340 * Replace the normal table with the checked table.
2342 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2344 assert(pVm->funcTable != &gCheckInvokeInterface);
2345 pVm->baseFuncTable = pVm->funcTable;
2346 pVm->funcTable = &gCheckInvokeInterface;