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 static void abortMaybe(void); // fwd
42 * ===========================================================================
43 * JNI call bridge wrapper
44 * ===========================================================================
48 * Check the result of a native method call that returns an object reference.
50 * The primary goal here is to verify that native code is returning the
51 * correct type of object. If it's declared to return a String but actually
52 * returns a byte array, things will fail in strange ways later on.
54 * This can be a fairly expensive operation, since we have to look up the
55 * return type class by name in method->clazz' class loader. We take a
56 * shortcut here and allow the call to succeed if the descriptor strings
57 * match. This will allow some false-positives when a class is redefined
58 * by a class loader, but that's rare enough that it doesn't seem worth
61 * At this point, pResult->l has already been converted to an object pointer.
63 static void checkCallCommon(const u4* args, JValue* pResult,
64 const Method* method, Thread* self)
66 assert(pResult->l != NULL);
67 Object* resultObj = (Object*) pResult->l;
68 ClassObject* objClazz = resultObj->clazz;
71 * Make sure that pResult->l is an instance of the type this
72 * method was expected to return.
74 const char* declType = dexProtoGetReturnType(&method->prototype);
75 const char* objType = objClazz->descriptor;
76 if (strcmp(declType, objType) == 0) {
77 /* names match; ignore class loader issues and allow it */
78 LOGV("Check %s.%s: %s io %s (FAST-OK)\n",
79 method->clazz->descriptor, method->name, objType, declType);
82 * Names didn't match. We need to resolve declType in the context
83 * of method->clazz->classLoader, and compare the class objects
86 * Since we're returning an instance of declType, it's safe to
87 * assume that it has been loaded and initialized (or, for the case
88 * of an array, generated), so we can just look for it in the
89 * loaded-classes list.
91 ClassObject* declClazz;
93 declClazz = dvmLookupClass(declType, method->clazz->classLoader, false);
94 if (declClazz == NULL) {
95 LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
97 LOGW(" failed in %s.%s ('%s' not found)\n",
98 method->clazz->descriptor, method->name, declType);
102 if (!dvmInstanceof(objClazz, declClazz)) {
103 LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
105 LOGW(" failed in %s.%s\n",
106 method->clazz->descriptor, method->name);
110 LOGV("Check %s.%s: %s io %s (SLOW-OK)\n",
111 method->clazz->descriptor, method->name, objType, declType);
117 * Determine if we need to check the return type coming out of the call.
119 * (We don't do this at the top of checkCallCommon() because this is on
120 * the critical path for native method calls.)
122 static inline bool callNeedsCheck(const u4* args, JValue* pResult,
123 const Method* method, Thread* self)
125 return (method->shorty[0] == 'L' && !dvmCheckException(self) &&
130 * Check a call into native code.
132 void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
133 const Method* method, Thread* self)
135 dvmCallJNIMethod_general(args, pResult, method, self);
136 if (callNeedsCheck(args, pResult, method, self))
137 checkCallCommon(args, pResult, method, self);
141 * Check a synchronized call into native code.
143 void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
144 const Method* method, Thread* self)
146 dvmCallJNIMethod_synchronized(args, pResult, method, self);
147 if (callNeedsCheck(args, pResult, method, self))
148 checkCallCommon(args, pResult, method, self);
152 * Check a virtual call with no reference arguments (other than "this").
154 void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
155 const Method* method, Thread* self)
157 dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
158 if (callNeedsCheck(args, pResult, method, self))
159 checkCallCommon(args, pResult, method, self);
163 * Check a static call with no reference arguments (other than "clazz").
165 void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
166 const Method* method, Thread* self)
168 dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
169 if (callNeedsCheck(args, pResult, method, self))
170 checkCallCommon(args, pResult, method, self);
175 * ===========================================================================
176 * JNI function helpers
177 * ===========================================================================
180 #define JNI_ENTER() dvmChangeStatus(NULL, THREAD_RUNNING)
181 #define JNI_EXIT() dvmChangeStatus(NULL, THREAD_NATIVE)
183 #define BASE_ENV(_env) (((JNIEnvExt*)_env)->baseFuncTable)
184 #define BASE_VM(_vm) (((JavaVMExt*)_vm)->baseFuncTable)
186 #define kRedundantDirectBufferTest false
189 * Flags passed into checkThread().
191 #define kFlag_Default 0x0000
193 #define kFlag_CritBad 0x0000 /* calling while in critical is bad */
194 #define kFlag_CritOkay 0x0001 /* ...okay */
195 #define kFlag_CritGet 0x0002 /* this is a critical "get" */
196 #define kFlag_CritRelease 0x0003 /* this is a critical "release" */
197 #define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
199 #define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
200 #define kFlag_ExcepOkay 0x0004 /* ...okay */
203 * Enter/exit macros for JNI env "check" functions. These do not change
204 * the thread state within the VM.
206 #define CHECK_ENTER(_env, _flags) \
208 JNI_TRACE(true, true); \
209 checkThread(_env, _flags, __FUNCTION__); \
212 #define CHECK_EXIT(_env) \
213 do { JNI_TRACE(false, true); } while(false)
217 * Enter/exit macros for JNI invocation interface "check" functions. These
218 * do not change the thread state within the VM.
220 * Set "_hasmeth" to true if we have a valid thread with a method pointer.
221 * We won't have one before attaching a thread, after detaching a thread, or
222 * after destroying the VM.
224 #define CHECK_VMENTER(_vm, _hasmeth) \
225 do { JNI_TRACE(true, _hasmeth); } while(false)
226 #define CHECK_VMEXIT(_vm, _hasmeth) \
227 do { JNI_TRACE(false, _hasmeth); } while(false)
229 #define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic) \
230 checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
231 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid) \
232 checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
233 #define CHECK_CLASS(_env, _clazz) \
234 checkClass(_env, _clazz, __FUNCTION__)
235 #define CHECK_STRING(_env, _str) \
236 checkString(_env, _str, __FUNCTION__)
237 #define CHECK_UTF_STRING(_env, _str, _nullok) \
238 checkUtfString(_env, _str, _nullok, __FUNCTION__)
239 #define CHECK_CLASS_NAME(_env, _str) \
240 checkClassName(_env, _str, __FUNCTION__)
241 #define CHECK_OBJECT(_env, _obj) \
242 checkObject(_env, _obj, __FUNCTION__)
243 #define CHECK_ARRAY(_env, _array) \
244 checkArray(_env, _array, __FUNCTION__)
245 #define CHECK_RELEASE_MODE(_env, _mode) \
246 checkReleaseMode(_env, _mode, __FUNCTION__)
247 #define CHECK_LENGTH_POSITIVE(_env, _length) \
248 checkLengthPositive(_env, _length, __FUNCTION__)
249 #define CHECK_NON_NULL(_env, _ptr) \
250 checkNonNull(_env, _ptr, __FUNCTION__)
252 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic) \
253 checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
256 * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
258 #define JNI_TRACE(_entry, _hasmeth) \
260 if (gDvm.verboseJni && (_entry)) { \
261 static const char* classDescriptor = "???"; \
262 static const char* methodName = "???"; \
264 const Method* meth = dvmGetCurrentJNIMethod(); \
265 classDescriptor = meth->clazz->descriptor; \
266 methodName = meth->name; \
268 /* use +6 to drop the leading "Check_" */ \
269 LOGI("JNI: %s (from %s.%s)", \
270 (__FUNCTION__)+6, classDescriptor, methodName); \
275 * Log the current location.
277 * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
279 static void showLocation(const Method* meth, const char* func)
281 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
282 LOGW(" in %s.%s %s (%s)\n",
283 meth->clazz->descriptor, meth->name, desc, func + 6);
288 * Abort if we are configured to bail out on JNI warnings.
290 static void abortMaybe(void)
292 JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
294 dvmDumpThread(dvmThreadSelf(), false);
300 * Verify that the current thread is (a) attached and (b) associated with
301 * this particular instance of JNIEnv.
303 * Verify that, if this thread previously made a critical "get" call, we
304 * do the corresponding "release" call before we try anything else.
306 * Verify that, if an exception has been raised, the native code doesn't
307 * make any JNI calls other than the Exception* methods.
309 * TODO? if we add support for non-JNI native calls, make sure that the
310 * method at the top of the interpreted stack is a JNI method call. (Or
311 * set a flag in the Thread/JNIEnv when the call is made and clear it on
314 * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
316 static void checkThread(JNIEnv* env, int flags, const char* func)
318 JNIEnvExt* threadEnv;
319 bool printWarn = false;
320 bool printException = false;
322 /* get the *correct* JNIEnv by going through our TLS pointer */
323 threadEnv = dvmGetJNIEnvForThread();
326 * Verify that the JNIEnv we've been handed matches what we expected
329 if (threadEnv == NULL) {
330 LOGE("JNI ERROR: non-VM thread making JNI calls\n");
331 // don't set printWarn -- it'll try to call showLocation()
333 } else if ((JNIEnvExt*) env != threadEnv) {
334 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
335 LOGE("JNI: threadEnv != thread->env?\n");
339 LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
340 threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
343 /* this is a bad idea -- need to throw as we exit, or abort func */
344 //dvmThrowException("Ljava/lang/RuntimeException;",
345 // "invalid use of JNI env ptr");
346 } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
347 /* correct JNIEnv*; make sure the "self" pointer is correct */
348 LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)\n",
349 ((JNIEnvExt*) env)->self, dvmThreadSelf());
354 * Check for critical resource misuse.
356 switch (flags & kFlag_CritMask) {
357 case kFlag_CritOkay: // okay to call this method
359 case kFlag_CritBad: // not okay to call
360 if (threadEnv->critical) {
361 LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
362 threadEnv->envThreadId);
366 case kFlag_CritGet: // this is a "get" call
367 /* don't check here; we allow nested gets */
368 threadEnv->critical++;
370 case kFlag_CritRelease: // this is a "release" call
371 threadEnv->critical--;
372 if (threadEnv->critical < 0) {
373 LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
374 threadEnv->envThreadId);
383 * Check for raised exceptions.
385 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
386 LOGW("JNI WARNING: JNI method called with exception raised\n");
388 printException = true;
392 showLocation(dvmGetCurrentJNIMethod(), func);
393 if (printException) {
394 LOGW("Pending exception is:\n");
395 dvmLogExceptionStackTrace();
402 * Verify that the field is of the appropriate type. If the field has an
403 * object type, "obj" is the object we're trying to assign into it.
405 * Works for both static and instance fields.
407 static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
408 PrimitiveType prim, bool isStatic, const char* func)
410 static const char* primNameList[] = {
411 "Object/Array", "boolean", "char", "float", "double",
412 "byte", "short", "int", "long", "void"
414 const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
415 Field* field = (Field*) fieldID;
416 bool printWarn = false;
418 if (fieldID == NULL) {
419 LOGE("JNI ERROR: null field ID\n");
423 if (field->signature[0] == 'L' || field->signature[0] == '[') {
424 Object* obj = dvmDecodeIndirectRef(env, jobj);
426 ClassObject* fieldClass =
427 dvmFindLoadedClass(field->signature);
428 ClassObject* objClass = obj->clazz;
430 assert(fieldClass != NULL);
431 assert(objClass != NULL);
433 if (!dvmInstanceof(objClass, fieldClass)) {
434 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
435 field->name, field->signature, objClass->descriptor);
439 } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
440 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
441 field->name, field->signature, primNames[prim]);
443 } else if (isStatic && !dvmIsStaticField(field)) {
445 LOGW("JNI WARNING: accessing non-static field %s as static\n",
448 LOGW("JNI WARNING: accessing static field %s as non-static\n",
454 showLocation(dvmGetCurrentJNIMethod(), func);
460 * Verify that "jobj" is a valid object, and that it's an object that JNI
461 * is allowed to know about. We allow NULL references.
463 * Switches to "running" mode before performing checks.
465 static void checkObject(JNIEnv* env, jobject jobj, const char* func)
467 UNUSED_PARAMETER(env);
468 bool printWarn = false;
475 if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
476 LOGW("JNI WARNING: %p is not a valid JNI reference\n", jobj);
479 Object* obj = dvmDecodeIndirectRef(env, jobj);
481 if (obj == NULL || !dvmIsValidObject(obj)) {
482 LOGW("JNI WARNING: native code passing in bad object %p %p (%s)\n",
489 showLocation(dvmGetCurrentJNIMethod(), func);
497 * Verify that "clazz" actually points to a class object. (Also performs
500 * We probably don't need to identify where we're being called from,
501 * because the VM is most likely about to crash and leave a core dump
502 * if something is wrong.
504 * Because we're looking at an object on the GC heap, we have to switch
505 * to "running" mode before doing the checks.
507 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
510 bool printWarn = false;
512 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
515 LOGW("JNI WARNING: received null jclass\n");
517 } else if (!dvmIsValidObject((Object*) clazz)) {
518 LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
520 } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
521 LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
522 jclazz, clazz->descriptor);
530 checkObject(env, jclazz, func);
534 * Verify that "str" is non-NULL and points to a String object.
536 * Since we're dealing with objects, switch to "running" mode.
538 static void checkString(JNIEnv* env, jstring jstr, const char* func)
541 bool printWarn = false;
543 Object* obj = dvmDecodeIndirectRef(env, jstr);
546 LOGW("JNI WARNING: received null jstring (%s)\n", func);
548 } else if (obj->clazz != gDvm.classJavaLangString) {
550 * TODO: we probably should test dvmIsValidObject first, because
551 * this will crash if "obj" is non-null but pointing to an invalid
552 * memory region. However, the "is valid" test is a little slow,
553 * we're doing it again over in checkObject().
555 if (dvmIsValidObject(obj))
556 LOGW("JNI WARNING: jstring %p points to non-string object (%s)\n",
559 LOGW("JNI WARNING: jstring %p is bogus (%s)\n", jstr, func);
567 checkObject(env, jstr, func);
571 * Verify that "bytes" points to valid "modified UTF-8" data.
573 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
576 const char* origBytes = bytes;
580 LOGW("JNI WARNING: unexpectedly null UTF string\n");
587 while (*bytes != '\0') {
588 u1 utf8 = *(bytes++);
589 // Switch on the high four bits.
599 // Bit pattern 0xxx. No need for any extra bytes.
608 * Bit pattern 10xx or 1111, which are illegal start bytes.
609 * Note: 1111 is valid for normal UTF-8, but not the
610 * modified UTF-8 used here.
612 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
616 // Bit pattern 1110, so there are two additional bytes.
618 if ((utf8 & 0xc0) != 0x80) {
619 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
622 // Fall through to take care of the final byte.
626 // Bit pattern 110x, so there is one additional byte.
628 if ((utf8 & 0xc0) != 0x80) {
629 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
640 LOGW(" string: '%s'\n", origBytes);
641 showLocation(dvmGetCurrentJNIMethod(), func);
646 * In some circumstances the VM will screen class names, but it doesn't
647 * for class lookup. When things get bounced through a class loader, they
648 * can actually get normalized a couple of times; as a result, passing in
649 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
650 * work in some circumstances.
652 * This is incorrect and could cause strange behavior or compatibility
653 * problems, so we want to screen that out here.
655 * We expect "full-qualified" class names, like "java/lang/Thread" or
656 * "[Ljava/lang/Object;".
658 static void checkClassName(JNIEnv* env, const char* className, const char* func)
662 /* quick check for illegal chars */
664 while (*cp != '\0') {
670 // TODO: need a more rigorous check here
675 LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
680 * Verify that "array" is non-NULL and points to an Array object.
682 * Since we're dealing with objects, switch to "running" mode.
684 static void checkArray(JNIEnv* env, jarray jarr, const char* func)
687 bool printWarn = false;
689 Object* obj = dvmDecodeIndirectRef(env, jarr);
692 LOGW("JNI WARNING: received null array (%s)\n", func);
694 } else if (obj->clazz->descriptor[0] != '[') {
695 if (dvmIsValidObject(obj))
696 LOGW("JNI WARNING: jarray %p points to non-array object (%s)\n",
697 jarr, obj->clazz->descriptor);
699 LOGW("JNI WARNING: jarray %p is bogus\n", jarr);
708 checkObject(env, jarr, func);
712 * Verify that the "mode" argument passed to a primitive array Release
713 * function is one of the valid values.
715 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
717 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
718 LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
724 * Verify that the length argument to array-creation calls is >= 0.
726 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
729 LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
735 * Verify that the pointer value is non-NULL.
737 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
740 LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
746 * Verify that the method's return type matches the type of call.
748 * "expectedSigByte" will be 'L' for all objects, including arrays.
750 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
751 bool isStatic, const char* func)
753 const Method* meth = (const Method*) methodID;
754 bool printWarn = false;
756 if (expectedSigByte != meth->shorty[0]) {
757 LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
759 } else if (isStatic && !dvmIsStaticMethod(meth)) {
761 LOGW("JNI WARNING: calling non-static method with static call\n");
763 LOGW("JNI WARNING: calling static method with non-static call\n");
768 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
769 LOGW(" calling %s.%s %s\n",
770 meth->clazz->descriptor, meth->name, desc);
772 showLocation(dvmGetCurrentJNIMethod(), func);
778 * Verify that this static field ID is valid for this class.
780 static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
782 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
783 StaticField* base = clazz->sfields;
784 int fieldCount = clazz->sfieldCount;
786 if ((StaticField*) fieldID < base ||
787 (StaticField*) fieldID >= base + fieldCount)
789 LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
790 fieldID, clazz->descriptor);
791 LOGW(" base=%p count=%d\n", base, fieldCount);
797 * Verify that this instance field ID is valid for this object.
799 static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
805 LOGW("JNI WARNING: invalid null object (%s)\n", func);
810 Object* obj = dvmDecodeIndirectRef(env, jobj);
811 ClassObject* clazz = obj->clazz;
814 * Check this class and all of its superclasses for a matching field.
815 * Don't need to scan interfaces.
817 while (clazz != NULL) {
818 if ((InstField*) fieldID >= clazz->ifields &&
819 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
824 clazz = clazz->super;
827 LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
828 fieldID, obj->clazz->descriptor);
837 * ===========================================================================
839 * ===========================================================================
842 #define kGuardLen 512 /* must be multiple of 2 */
843 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
844 #define kGuardMagic 0xffd5aa96
845 #define kGuardExtra sizeof(GuardExtra)
847 /* this gets tucked in at the start of the buffer; struct size must be even */
848 typedef struct GuardExtra {
852 const void* originalPtr;
855 /* find the GuardExtra given the pointer into the "live" data */
856 inline static GuardExtra* getGuardExtra(const void* dataBuf)
858 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
859 return (GuardExtra*) fullBuf;
863 * Create an oversized buffer to hold the contents of "buf". Copy it in,
864 * filling in the area around it with guard data.
866 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
868 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
871 size_t newLen = (len + kGuardLen +1) & ~0x01;
876 newBuf = (u1*)malloc(newLen);
877 if (newBuf == NULL) {
878 LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
882 /* fill it in with a pattern */
884 for (i = 0; i < (int)newLen / 2; i++)
885 *pat++ = kGuardPattern;
887 /* copy the data in; note "len" could be zero */
888 memcpy(newBuf + kGuardLen / 2, buf, len);
890 /* if modification is not expected, grab a checksum */
893 adler = adler32(0L, Z_NULL, 0);
894 adler = adler32(adler, buf, len);
895 *(uLong*)newBuf = adler;
898 pExtra = (GuardExtra*) newBuf;
899 pExtra->magic = kGuardMagic;
900 pExtra->adler = adler;
901 pExtra->originalPtr = buf;
902 pExtra->originalLen = len;
904 return newBuf + kGuardLen / 2;
908 * Verify the guard area and, if "modOkay" is false, that the data itself
909 * has not been altered.
911 * The caller has already checked that "dataBuf" is non-NULL.
913 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
915 static const u4 kMagicCmp = kGuardMagic;
916 const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
917 const GuardExtra* pExtra = getGuardExtra(dataBuf);
923 * Before we do anything with "pExtra", check the magic number. We
924 * do the check with memcmp rather than "==" in case the pointer is
925 * unaligned. If it points to completely bogus memory we're going
926 * to crash, but there's no easy way around that.
928 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
930 memcpy(buf, &pExtra->magic, 4);
931 LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
932 "-- incorrect data pointer %p?\n",
933 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
937 len = pExtra->originalLen;
939 /* check bottom half of guard; skip over optional checksum storage */
941 for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
943 if (pat[i] != kGuardPattern) {
944 LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
950 int offset = kGuardLen / 2 + len;
952 /* odd byte; expected value depends on endian-ness of host */
953 const u2 patSample = kGuardPattern;
954 if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
955 LOGE("JNI: guard pattern disturbed in odd byte after %p "
956 "(+%d) 0x%02x 0x%02x\n",
957 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
963 /* check top half of guard */
964 pat = (u2*) (fullBuf + offset);
965 for (i = 0; i < kGuardLen / 4; i++) {
966 if (pat[i] != kGuardPattern) {
967 LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
968 fullBuf, offset + i*2);
974 * If modification is not expected, verify checksum. Strictly speaking
975 * this is wrong: if we told the client that we made a copy, there's no
976 * reason they can't alter the buffer.
979 uLong adler = adler32(0L, Z_NULL, 0);
980 adler = adler32(adler, dataBuf, len);
981 if (pExtra->adler != adler) {
982 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
983 pExtra->adler, adler, dataBuf);
992 * Free up the guard buffer, scrub it, and return the original pointer.
994 static void* freeGuardedCopy(void* dataBuf)
996 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
997 const GuardExtra* pExtra = getGuardExtra(dataBuf);
998 void* originalPtr = (void*) pExtra->originalPtr;
999 size_t len = pExtra->originalLen;
1001 memset(dataBuf, 0xdd, len);
1007 * Just pull out the original pointer.
1009 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
1011 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1012 return (void*) pExtra->originalPtr;
1016 * Grab the data length.
1018 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
1020 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1021 return pExtra->originalLen;
1025 * Return the width, in bytes, of a primitive type.
1027 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
1029 static const int lengths[PRIM_MAX] = {
1040 assert(primType >= 0 && primType < PRIM_MAX);
1041 return lengths[primType];
1045 * Create a guarded copy of a primitive array. Modifications to the copied
1046 * data are allowed. Returns a pointer to the copied data.
1048 static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
1051 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1052 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1053 int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1056 result = createGuardedCopy(arrObj->contents, len, true);
1065 * Perform the array "release" operation, which may or may not copy data
1066 * back into the VM, and may or may not release the underlying storage.
1068 static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
1071 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1072 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1073 //int len = array->length * dvmPrimitiveTypeWidth(primType);
1074 bool release, copyBack;
1077 if (!checkGuardedCopy(dataBuf, true)) {
1078 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
1085 release = copyBack = true;
1096 LOGE("JNI: bad release mode %d\n", mode);
1102 size_t len = getGuardedCopyOriginalLen(dataBuf);
1103 memcpy(arrObj->contents, dataBuf, len);
1107 result = (u1*) freeGuardedCopy(dataBuf);
1109 result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
1112 /* pointer is to the array contents; back up to the array object */
1113 result -= offsetof(ArrayObject, contents);
1120 * ===========================================================================
1122 * ===========================================================================
1125 static jint Check_GetVersion(JNIEnv* env)
1127 CHECK_ENTER(env, kFlag_Default);
1129 result = BASE_ENV(env)->GetVersion(env);
1134 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1135 const jbyte* buf, jsize bufLen)
1137 CHECK_ENTER(env, kFlag_Default);
1138 CHECK_OBJECT(env, loader);
1139 CHECK_UTF_STRING(env, name, false);
1140 CHECK_CLASS_NAME(env, name);
1142 result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
1147 static jclass Check_FindClass(JNIEnv* env, const char* name)
1149 CHECK_ENTER(env, kFlag_Default);
1150 CHECK_UTF_STRING(env, name, false);
1151 CHECK_CLASS_NAME(env, name);
1153 result = BASE_ENV(env)->FindClass(env, name);
1158 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
1160 CHECK_ENTER(env, kFlag_Default);
1161 CHECK_CLASS(env, clazz);
1163 result = BASE_ENV(env)->GetSuperclass(env, clazz);
1168 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1171 CHECK_ENTER(env, kFlag_Default);
1172 CHECK_CLASS(env, clazz1);
1173 CHECK_CLASS(env, clazz2);
1175 result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1180 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1182 CHECK_ENTER(env, kFlag_Default);
1183 CHECK_OBJECT(env, method);
1185 result = BASE_ENV(env)->FromReflectedMethod(env, method);
1190 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1192 CHECK_ENTER(env, kFlag_Default);
1193 CHECK_OBJECT(env, field);
1195 result = BASE_ENV(env)->FromReflectedField(env, field);
1200 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1201 jmethodID methodID, jboolean isStatic)
1203 CHECK_ENTER(env, kFlag_Default);
1204 CHECK_CLASS(env, cls);
1206 result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1211 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1214 CHECK_ENTER(env, kFlag_Default);
1215 CHECK_CLASS(env, cls);
1217 result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1222 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1224 CHECK_ENTER(env, kFlag_Default);
1225 CHECK_OBJECT(env, obj);
1227 result = BASE_ENV(env)->Throw(env, obj);
1232 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1234 CHECK_ENTER(env, kFlag_Default);
1235 CHECK_CLASS(env, clazz);
1236 CHECK_UTF_STRING(env, message, true);
1238 result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1243 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1245 CHECK_ENTER(env, kFlag_ExcepOkay);
1247 result = BASE_ENV(env)->ExceptionOccurred(env);
1252 static void Check_ExceptionDescribe(JNIEnv* env)
1254 CHECK_ENTER(env, kFlag_ExcepOkay);
1255 BASE_ENV(env)->ExceptionDescribe(env);
1259 static void Check_ExceptionClear(JNIEnv* env)
1261 CHECK_ENTER(env, kFlag_ExcepOkay);
1262 BASE_ENV(env)->ExceptionClear(env);
1266 static void Check_FatalError(JNIEnv* env, const char* msg)
1268 CHECK_ENTER(env, kFlag_Default);
1269 CHECK_UTF_STRING(env, msg, true);
1270 BASE_ENV(env)->FatalError(env, msg);
1274 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1276 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1278 result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1283 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1285 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1286 CHECK_OBJECT(env, res);
1288 result = BASE_ENV(env)->PopLocalFrame(env, res);
1293 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1295 CHECK_ENTER(env, kFlag_Default);
1296 CHECK_OBJECT(env, obj);
1298 result = BASE_ENV(env)->NewGlobalRef(env, obj);
1303 static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
1305 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1306 CHECK_OBJECT(env, globalRef);
1307 #ifdef USE_INDIRECT_REF
1308 if (globalRef != NULL &&
1309 dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
1311 LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)\n",
1312 globalRef, dvmGetJNIRefType(env, globalRef));
1317 BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
1322 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1324 CHECK_ENTER(env, kFlag_Default);
1325 CHECK_OBJECT(env, ref);
1327 result = BASE_ENV(env)->NewLocalRef(env, ref);
1332 static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
1334 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1335 CHECK_OBJECT(env, localRef);
1336 #ifdef USE_INDIRECT_REF
1337 if (localRef != NULL &&
1338 dvmGetJNIRefType(env, localRef) != JNILocalRefType)
1340 LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)\n",
1341 localRef, dvmGetJNIRefType(env, localRef));
1346 BASE_ENV(env)->DeleteLocalRef(env, localRef);
1351 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1353 CHECK_ENTER(env, kFlag_Default);
1355 result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1360 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1362 CHECK_ENTER(env, kFlag_Default);
1363 CHECK_OBJECT(env, ref1);
1364 CHECK_OBJECT(env, ref2);
1366 result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1371 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1373 CHECK_ENTER(env, kFlag_Default);
1374 CHECK_CLASS(env, clazz);
1376 result = BASE_ENV(env)->AllocObject(env, clazz);
1381 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1384 CHECK_ENTER(env, kFlag_Default);
1385 CHECK_CLASS(env, clazz);
1389 va_start(args, methodID);
1390 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1396 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1399 CHECK_ENTER(env, kFlag_Default);
1400 CHECK_CLASS(env, clazz);
1402 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1406 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1409 CHECK_ENTER(env, kFlag_Default);
1410 CHECK_CLASS(env, clazz);
1412 result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1417 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1419 CHECK_ENTER(env, kFlag_Default);
1420 CHECK_OBJECT(env, obj);
1422 result = BASE_ENV(env)->GetObjectClass(env, obj);
1427 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1429 CHECK_ENTER(env, kFlag_Default);
1430 CHECK_OBJECT(env, obj);
1431 CHECK_CLASS(env, clazz);
1433 result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1438 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1441 CHECK_ENTER(env, kFlag_Default);
1442 CHECK_CLASS(env, clazz);
1443 CHECK_UTF_STRING(env, name, false);
1444 CHECK_UTF_STRING(env, sig, false);
1446 result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1451 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1452 const char* name, const char* sig)
1454 CHECK_ENTER(env, kFlag_Default);
1455 CHECK_CLASS(env, clazz);
1456 CHECK_UTF_STRING(env, name, false);
1457 CHECK_UTF_STRING(env, sig, false);
1459 result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1464 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1465 const char* name, const char* sig)
1467 CHECK_ENTER(env, kFlag_Default);
1468 CHECK_CLASS(env, clazz);
1469 CHECK_UTF_STRING(env, name, false);
1470 CHECK_UTF_STRING(env, sig, false);
1472 result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1477 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1478 const char* name, const char* sig)
1480 CHECK_ENTER(env, kFlag_Default);
1481 CHECK_CLASS(env, clazz);
1482 CHECK_UTF_STRING(env, name, false);
1483 CHECK_UTF_STRING(env, sig, false);
1485 result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1490 #define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
1491 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1494 CHECK_ENTER(env, kFlag_Default); \
1495 CHECK_CLASS(env, clazz); \
1497 checkStaticFieldID(env, clazz, fieldID); \
1498 result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
1503 GET_STATIC_TYPE_FIELD(jobject, Object);
1504 GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1505 GET_STATIC_TYPE_FIELD(jbyte, Byte);
1506 GET_STATIC_TYPE_FIELD(jchar, Char);
1507 GET_STATIC_TYPE_FIELD(jshort, Short);
1508 GET_STATIC_TYPE_FIELD(jint, Int);
1509 GET_STATIC_TYPE_FIELD(jlong, Long);
1510 GET_STATIC_TYPE_FIELD(jfloat, Float);
1511 GET_STATIC_TYPE_FIELD(jdouble, Double);
1513 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1514 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1515 jfieldID fieldID, _ctype value) \
1517 CHECK_ENTER(env, kFlag_Default); \
1518 CHECK_CLASS(env, clazz); \
1519 checkStaticFieldID(env, clazz, fieldID); \
1520 /* "value" arg only used when type == ref */ \
1521 CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true); \
1522 BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
1526 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1527 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1528 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1529 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1530 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1531 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1532 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1533 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1534 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1536 #define GET_TYPE_FIELD(_ctype, _jname) \
1537 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
1540 CHECK_ENTER(env, kFlag_Default); \
1541 CHECK_OBJECT(env, obj); \
1543 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1544 result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
1548 GET_TYPE_FIELD(jobject, Object);
1549 GET_TYPE_FIELD(jboolean, Boolean);
1550 GET_TYPE_FIELD(jbyte, Byte);
1551 GET_TYPE_FIELD(jchar, Char);
1552 GET_TYPE_FIELD(jshort, Short);
1553 GET_TYPE_FIELD(jint, Int);
1554 GET_TYPE_FIELD(jlong, Long);
1555 GET_TYPE_FIELD(jfloat, Float);
1556 GET_TYPE_FIELD(jdouble, Double);
1558 #define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1559 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
1560 jfieldID fieldID, _ctype value) \
1562 CHECK_ENTER(env, kFlag_Default); \
1563 CHECK_OBJECT(env, obj); \
1564 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1565 /* "value" arg only used when type == ref */ \
1566 CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
1567 BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
1570 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1571 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1572 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1573 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1574 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1575 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1576 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1577 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1578 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1580 #define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1581 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
1582 jmethodID methodID, ...) \
1584 CHECK_ENTER(env, kFlag_Default); \
1585 CHECK_OBJECT(env, obj); \
1586 CHECK_SIG(env, methodID, _retsig, false); \
1589 va_start(args, methodID); \
1590 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1596 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1597 jmethodID methodID, va_list args) \
1599 CHECK_ENTER(env, kFlag_Default); \
1600 CHECK_OBJECT(env, obj); \
1601 CHECK_SIG(env, methodID, _retsig, false); \
1603 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1608 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1609 jmethodID methodID, jvalue* args) \
1611 CHECK_ENTER(env, kFlag_Default); \
1612 CHECK_OBJECT(env, obj); \
1613 CHECK_SIG(env, methodID, _retsig, false); \
1615 _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
1620 CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1621 CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1622 CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1623 CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1624 CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1625 CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
1626 CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1627 CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1628 CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1629 CALL_VIRTUAL(void, Void, , , , 'V');
1631 #define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \
1633 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
1634 jobject obj, jclass clazz, jmethodID methodID, ...) \
1636 CHECK_ENTER(env, kFlag_Default); \
1637 CHECK_CLASS(env, clazz); \
1638 CHECK_OBJECT(env, obj); \
1639 CHECK_SIG(env, methodID, _retsig, false); \
1642 va_start(args, methodID); \
1643 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1644 clazz, methodID, args); \
1649 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1650 jobject obj, jclass clazz, jmethodID methodID, va_list args) \
1652 CHECK_ENTER(env, kFlag_Default); \
1653 CHECK_CLASS(env, clazz); \
1654 CHECK_OBJECT(env, obj); \
1655 CHECK_SIG(env, methodID, _retsig, false); \
1657 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1658 clazz, methodID, args); \
1662 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1663 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
1665 CHECK_ENTER(env, kFlag_Default); \
1666 CHECK_CLASS(env, clazz); \
1667 CHECK_OBJECT(env, obj); \
1668 CHECK_SIG(env, methodID, _retsig, false); \
1670 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
1671 clazz, methodID, args); \
1675 CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1676 CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1677 CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1678 CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1679 CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1680 CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
1681 CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1682 CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1683 CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1684 CALL_NONVIRTUAL(void, Void, , , , 'V');
1687 #define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1688 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
1689 jclass clazz, jmethodID methodID, ...) \
1691 CHECK_ENTER(env, kFlag_Default); \
1692 CHECK_CLASS(env, clazz); \
1693 CHECK_SIG(env, methodID, _retsig, true); \
1696 va_start(args, methodID); \
1697 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1703 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
1704 jclass clazz, jmethodID methodID, va_list args) \
1706 CHECK_ENTER(env, kFlag_Default); \
1707 CHECK_CLASS(env, clazz); \
1708 CHECK_SIG(env, methodID, _retsig, true); \
1710 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1715 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
1716 jclass clazz, jmethodID methodID, jvalue* args) \
1718 CHECK_ENTER(env, kFlag_Default); \
1719 CHECK_CLASS(env, clazz); \
1720 CHECK_SIG(env, methodID, _retsig, true); \
1722 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
1727 CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
1728 CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
1729 CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
1730 CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
1731 CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
1732 CALL_STATIC(jint, Int, jint result, result=, result, 'I');
1733 CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
1734 CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
1735 CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
1736 CALL_STATIC(void, Void, , , , 'V');
1738 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1741 CHECK_ENTER(env, kFlag_Default);
1743 result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1748 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1750 CHECK_ENTER(env, kFlag_CritOkay);
1751 CHECK_STRING(env, string);
1753 result = BASE_ENV(env)->GetStringLength(env, string);
1758 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1761 CHECK_ENTER(env, kFlag_CritOkay);
1762 CHECK_STRING(env, string);
1763 const jchar* result;
1764 result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1765 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1766 // TODO: fix for indirect
1767 int len = dvmStringLen(string) * 2;
1768 result = (const jchar*) createGuardedCopy(result, len, false);
1776 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1779 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1780 CHECK_STRING(env, string);
1781 CHECK_NON_NULL(env, chars);
1782 if (((JNIEnvExt*)env)->forceDataCopy) {
1783 if (!checkGuardedCopy(chars, false)) {
1784 LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1788 chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1790 BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1794 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1796 CHECK_ENTER(env, kFlag_Default);
1797 CHECK_UTF_STRING(env, bytes, true);
1799 result = BASE_ENV(env)->NewStringUTF(env, bytes);
1804 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1806 CHECK_ENTER(env, kFlag_CritOkay);
1807 CHECK_STRING(env, string);
1809 result = BASE_ENV(env)->GetStringUTFLength(env, string);
1814 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1817 CHECK_ENTER(env, kFlag_CritOkay);
1818 CHECK_STRING(env, string);
1820 result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1821 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1822 // TODO: fix for indirect
1823 int len = dvmStringUtf8ByteLen(string) + 1;
1824 result = (const char*) createGuardedCopy(result, len, false);
1832 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1835 CHECK_ENTER(env, kFlag_ExcepOkay);
1836 CHECK_STRING(env, string);
1837 CHECK_NON_NULL(env, utf);
1838 if (((JNIEnvExt*)env)->forceDataCopy) {
1839 //int len = dvmStringUtf8ByteLen(string) + 1;
1840 if (!checkGuardedCopy(utf, false)) {
1841 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1845 utf = (const char*) freeGuardedCopy((char*)utf);
1847 BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1851 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1853 CHECK_ENTER(env, kFlag_CritOkay);
1854 CHECK_ARRAY(env, array);
1856 result = BASE_ENV(env)->GetArrayLength(env, array);
1861 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
1862 jclass elementClass, jobject initialElement)
1864 CHECK_ENTER(env, kFlag_Default);
1865 CHECK_CLASS(env, elementClass);
1866 CHECK_OBJECT(env, initialElement);
1867 CHECK_LENGTH_POSITIVE(env, length);
1868 jobjectArray result;
1869 result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
1875 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
1878 CHECK_ENTER(env, kFlag_Default);
1879 CHECK_ARRAY(env, array);
1881 result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
1886 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
1887 jsize index, jobject value)
1889 CHECK_ENTER(env, kFlag_Default);
1890 CHECK_ARRAY(env, array);
1891 BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
1895 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
1896 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
1898 CHECK_ENTER(env, kFlag_Default); \
1899 CHECK_LENGTH_POSITIVE(env, length); \
1901 result = BASE_ENV(env)->New##_jname##Array(env, length); \
1905 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
1906 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
1907 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
1908 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
1909 NEW_PRIMITIVE_ARRAY(jintArray, Int);
1910 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
1911 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
1912 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
1915 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1916 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
1917 _ctype##Array array, jboolean* isCopy) \
1919 CHECK_ENTER(env, kFlag_Default); \
1920 CHECK_ARRAY(env, array); \
1922 result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
1924 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
1925 result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
1931 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
1932 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
1933 _ctype##Array array, _ctype* elems, jint mode) \
1935 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
1936 CHECK_ARRAY(env, array); \
1937 CHECK_NON_NULL(env, elems); \
1938 CHECK_RELEASE_MODE(env, mode); \
1939 if (((JNIEnvExt*)env)->forceDataCopy) { \
1940 elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
1942 BASE_ENV(env)->Release##_jname##ArrayElements(env, \
1943 array, elems, mode); \
1947 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1948 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
1949 _ctype##Array array, jsize start, jsize len, _ctype* buf) \
1951 CHECK_ENTER(env, kFlag_Default); \
1952 CHECK_ARRAY(env, array); \
1953 BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
1958 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
1959 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
1960 _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
1962 CHECK_ENTER(env, kFlag_Default); \
1963 CHECK_ARRAY(env, array); \
1964 BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
1969 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
1970 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1971 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
1972 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
1973 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
1975 /* TODO: verify primitive array type matches call type */
1976 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
1977 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
1978 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
1979 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
1980 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
1981 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
1982 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
1983 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
1985 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
1986 const JNINativeMethod* methods, jint nMethods)
1988 CHECK_ENTER(env, kFlag_Default);
1989 CHECK_CLASS(env, clazz);
1991 result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
1996 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
1998 CHECK_ENTER(env, kFlag_Default);
1999 CHECK_CLASS(env, clazz);
2001 result = BASE_ENV(env)->UnregisterNatives(env, clazz);
2006 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
2008 CHECK_ENTER(env, kFlag_Default);
2009 CHECK_OBJECT(env, obj);
2011 result = BASE_ENV(env)->MonitorEnter(env, obj);
2016 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
2018 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2019 CHECK_OBJECT(env, obj);
2021 result = BASE_ENV(env)->MonitorExit(env, obj);
2026 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
2028 CHECK_ENTER(env, kFlag_Default);
2030 result = BASE_ENV(env)->GetJavaVM(env, vm);
2035 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
2036 jsize len, jchar* buf)
2038 CHECK_ENTER(env, kFlag_CritOkay);
2039 CHECK_STRING(env, str);
2040 BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
2044 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
2045 jsize len, char* buf)
2047 CHECK_ENTER(env, kFlag_CritOkay);
2048 CHECK_STRING(env, str);
2049 BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
2053 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
2056 CHECK_ENTER(env, kFlag_CritGet);
2057 CHECK_ARRAY(env, array);
2059 result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
2060 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2061 result = createGuardedPACopy(env, array, isCopy);
2067 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
2068 void* carray, jint mode)
2070 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2071 CHECK_ARRAY(env, array);
2072 CHECK_NON_NULL(env, carray);
2073 CHECK_RELEASE_MODE(env, mode);
2074 if (((JNIEnvExt*)env)->forceDataCopy) {
2075 carray = releaseGuardedPACopy(env, array, carray, mode);
2077 BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2081 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
2084 CHECK_ENTER(env, kFlag_CritGet);
2085 CHECK_STRING(env, string);
2086 const jchar* result;
2087 result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
2088 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2089 // TODO: fix for indirect
2090 int len = dvmStringLen(string) * 2;
2091 result = (const jchar*) createGuardedCopy(result, len, false);
2099 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
2100 const jchar* carray)
2102 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2103 CHECK_STRING(env, string);
2104 CHECK_NON_NULL(env, carray);
2105 if (((JNIEnvExt*)env)->forceDataCopy) {
2106 if (!checkGuardedCopy(carray, false)) {
2107 LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
2111 carray = (const jchar*) freeGuardedCopy((jchar*)carray);
2113 BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
2117 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
2119 CHECK_ENTER(env, kFlag_Default);
2120 CHECK_OBJECT(env, obj);
2122 result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
2127 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
2129 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2130 CHECK_OBJECT(env, obj);
2131 BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
2135 static jboolean Check_ExceptionCheck(JNIEnv* env)
2137 CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
2139 result = BASE_ENV(env)->ExceptionCheck(env);
2144 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
2146 CHECK_ENTER(env, kFlag_Default);
2147 CHECK_OBJECT(env, obj);
2148 jobjectRefType result;
2149 result = BASE_ENV(env)->GetObjectRefType(env, obj);
2154 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
2157 CHECK_ENTER(env, kFlag_Default);
2159 if (address == NULL || capacity < 0) {
2160 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
2161 address, (long) capacity);
2165 result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
2170 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
2172 CHECK_ENTER(env, kFlag_Default);
2173 CHECK_OBJECT(env, buf);
2174 void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
2177 /* optional - check result vs. "safe" implementation */
2178 if (kRedundantDirectBufferTest) {
2179 jobject platformAddr = NULL;
2180 void* checkResult = NULL;
2183 * Start by determining if the object supports the DirectBuffer
2184 * interfaces. Note this does not guarantee that it's a direct buffer.
2186 if (JNI_FALSE == (*env)->IsInstanceOf(env, buf,
2187 gDvm.jclassOrgApacheHarmonyNioInternalDirectBuffer))
2193 * Get the PlatformAddress object.
2195 * If this isn't a direct buffer, platformAddr will be NULL and/or an
2196 * exception will have been thrown.
2198 platformAddr = (*env)->CallObjectMethod(env, buf,
2199 (jmethodID) gDvm.methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress);
2201 if ((*env)->ExceptionCheck(env)) {
2202 (*env)->ExceptionClear(env);
2203 platformAddr = NULL;
2205 if (platformAddr == NULL) {
2206 LOGV("Got request for address of non-direct buffer\n");
2210 jclass platformAddrClass = (*env)->FindClass(env,
2211 "org/apache/harmony/luni/platform/PlatformAddress");
2212 jmethodID toLongMethod = (*env)->GetMethodID(env, platformAddrClass,
2214 checkResult = (void*)(u4)(*env)->CallLongMethod(env, platformAddr,
2218 if (platformAddr != NULL)
2219 (*env)->DeleteLocalRef(env, platformAddr);
2221 if (result != checkResult) {
2222 LOGW("JNI WARNING: direct buffer result mismatch (%p vs %p)\n",
2223 result, checkResult);
2232 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
2234 CHECK_ENTER(env, kFlag_Default);
2235 CHECK_OBJECT(env, buf);
2236 /* TODO: verify "buf" is an instance of java.nio.Buffer */
2237 jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2244 * ===========================================================================
2245 * JNI invocation functions
2246 * ===========================================================================
2249 static jint Check_DestroyJavaVM(JavaVM* vm)
2251 CHECK_VMENTER(vm, false);
2253 result = BASE_VM(vm)->DestroyJavaVM(vm);
2254 CHECK_VMEXIT(vm, false);
2258 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2261 CHECK_VMENTER(vm, false);
2263 result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2264 CHECK_VMEXIT(vm, true);
2268 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2271 CHECK_VMENTER(vm, false);
2273 result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2274 CHECK_VMEXIT(vm, true);
2278 static jint Check_DetachCurrentThread(JavaVM* vm)
2280 CHECK_VMENTER(vm, true);
2282 result = BASE_VM(vm)->DetachCurrentThread(vm);
2283 CHECK_VMEXIT(vm, false);
2287 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2289 CHECK_VMENTER(vm, true);
2291 result = BASE_VM(vm)->GetEnv(vm, env, version);
2292 CHECK_VMEXIT(vm, true);
2298 * ===========================================================================
2300 * ===========================================================================
2303 static const struct JNINativeInterface gCheckNativeInterface = {
2314 Check_FromReflectedMethod,
2315 Check_FromReflectedField,
2316 Check_ToReflectedMethod,
2318 Check_GetSuperclass,
2319 Check_IsAssignableFrom,
2321 Check_ToReflectedField,
2325 Check_ExceptionOccurred,
2326 Check_ExceptionDescribe,
2327 Check_ExceptionClear,
2330 Check_PushLocalFrame,
2331 Check_PopLocalFrame,
2334 Check_DeleteGlobalRef,
2335 Check_DeleteLocalRef,
2338 Check_EnsureLocalCapacity,
2345 Check_GetObjectClass,
2350 Check_CallObjectMethod,
2351 Check_CallObjectMethodV,
2352 Check_CallObjectMethodA,
2353 Check_CallBooleanMethod,
2354 Check_CallBooleanMethodV,
2355 Check_CallBooleanMethodA,
2356 Check_CallByteMethod,
2357 Check_CallByteMethodV,
2358 Check_CallByteMethodA,
2359 Check_CallCharMethod,
2360 Check_CallCharMethodV,
2361 Check_CallCharMethodA,
2362 Check_CallShortMethod,
2363 Check_CallShortMethodV,
2364 Check_CallShortMethodA,
2365 Check_CallIntMethod,
2366 Check_CallIntMethodV,
2367 Check_CallIntMethodA,
2368 Check_CallLongMethod,
2369 Check_CallLongMethodV,
2370 Check_CallLongMethodA,
2371 Check_CallFloatMethod,
2372 Check_CallFloatMethodV,
2373 Check_CallFloatMethodA,
2374 Check_CallDoubleMethod,
2375 Check_CallDoubleMethodV,
2376 Check_CallDoubleMethodA,
2377 Check_CallVoidMethod,
2378 Check_CallVoidMethodV,
2379 Check_CallVoidMethodA,
2381 Check_CallNonvirtualObjectMethod,
2382 Check_CallNonvirtualObjectMethodV,
2383 Check_CallNonvirtualObjectMethodA,
2384 Check_CallNonvirtualBooleanMethod,
2385 Check_CallNonvirtualBooleanMethodV,
2386 Check_CallNonvirtualBooleanMethodA,
2387 Check_CallNonvirtualByteMethod,
2388 Check_CallNonvirtualByteMethodV,
2389 Check_CallNonvirtualByteMethodA,
2390 Check_CallNonvirtualCharMethod,
2391 Check_CallNonvirtualCharMethodV,
2392 Check_CallNonvirtualCharMethodA,
2393 Check_CallNonvirtualShortMethod,
2394 Check_CallNonvirtualShortMethodV,
2395 Check_CallNonvirtualShortMethodA,
2396 Check_CallNonvirtualIntMethod,
2397 Check_CallNonvirtualIntMethodV,
2398 Check_CallNonvirtualIntMethodA,
2399 Check_CallNonvirtualLongMethod,
2400 Check_CallNonvirtualLongMethodV,
2401 Check_CallNonvirtualLongMethodA,
2402 Check_CallNonvirtualFloatMethod,
2403 Check_CallNonvirtualFloatMethodV,
2404 Check_CallNonvirtualFloatMethodA,
2405 Check_CallNonvirtualDoubleMethod,
2406 Check_CallNonvirtualDoubleMethodV,
2407 Check_CallNonvirtualDoubleMethodA,
2408 Check_CallNonvirtualVoidMethod,
2409 Check_CallNonvirtualVoidMethodV,
2410 Check_CallNonvirtualVoidMethodA,
2414 Check_GetObjectField,
2415 Check_GetBooleanField,
2418 Check_GetShortField,
2421 Check_GetFloatField,
2422 Check_GetDoubleField,
2423 Check_SetObjectField,
2424 Check_SetBooleanField,
2427 Check_SetShortField,
2430 Check_SetFloatField,
2431 Check_SetDoubleField,
2433 Check_GetStaticMethodID,
2435 Check_CallStaticObjectMethod,
2436 Check_CallStaticObjectMethodV,
2437 Check_CallStaticObjectMethodA,
2438 Check_CallStaticBooleanMethod,
2439 Check_CallStaticBooleanMethodV,
2440 Check_CallStaticBooleanMethodA,
2441 Check_CallStaticByteMethod,
2442 Check_CallStaticByteMethodV,
2443 Check_CallStaticByteMethodA,
2444 Check_CallStaticCharMethod,
2445 Check_CallStaticCharMethodV,
2446 Check_CallStaticCharMethodA,
2447 Check_CallStaticShortMethod,
2448 Check_CallStaticShortMethodV,
2449 Check_CallStaticShortMethodA,
2450 Check_CallStaticIntMethod,
2451 Check_CallStaticIntMethodV,
2452 Check_CallStaticIntMethodA,
2453 Check_CallStaticLongMethod,
2454 Check_CallStaticLongMethodV,
2455 Check_CallStaticLongMethodA,
2456 Check_CallStaticFloatMethod,
2457 Check_CallStaticFloatMethodV,
2458 Check_CallStaticFloatMethodA,
2459 Check_CallStaticDoubleMethod,
2460 Check_CallStaticDoubleMethodV,
2461 Check_CallStaticDoubleMethodA,
2462 Check_CallStaticVoidMethod,
2463 Check_CallStaticVoidMethodV,
2464 Check_CallStaticVoidMethodA,
2466 Check_GetStaticFieldID,
2468 Check_GetStaticObjectField,
2469 Check_GetStaticBooleanField,
2470 Check_GetStaticByteField,
2471 Check_GetStaticCharField,
2472 Check_GetStaticShortField,
2473 Check_GetStaticIntField,
2474 Check_GetStaticLongField,
2475 Check_GetStaticFloatField,
2476 Check_GetStaticDoubleField,
2478 Check_SetStaticObjectField,
2479 Check_SetStaticBooleanField,
2480 Check_SetStaticByteField,
2481 Check_SetStaticCharField,
2482 Check_SetStaticShortField,
2483 Check_SetStaticIntField,
2484 Check_SetStaticLongField,
2485 Check_SetStaticFloatField,
2486 Check_SetStaticDoubleField,
2490 Check_GetStringLength,
2491 Check_GetStringChars,
2492 Check_ReleaseStringChars,
2495 Check_GetStringUTFLength,
2496 Check_GetStringUTFChars,
2497 Check_ReleaseStringUTFChars,
2499 Check_GetArrayLength,
2500 Check_NewObjectArray,
2501 Check_GetObjectArrayElement,
2502 Check_SetObjectArrayElement,
2504 Check_NewBooleanArray,
2507 Check_NewShortArray,
2510 Check_NewFloatArray,
2511 Check_NewDoubleArray,
2513 Check_GetBooleanArrayElements,
2514 Check_GetByteArrayElements,
2515 Check_GetCharArrayElements,
2516 Check_GetShortArrayElements,
2517 Check_GetIntArrayElements,
2518 Check_GetLongArrayElements,
2519 Check_GetFloatArrayElements,
2520 Check_GetDoubleArrayElements,
2522 Check_ReleaseBooleanArrayElements,
2523 Check_ReleaseByteArrayElements,
2524 Check_ReleaseCharArrayElements,
2525 Check_ReleaseShortArrayElements,
2526 Check_ReleaseIntArrayElements,
2527 Check_ReleaseLongArrayElements,
2528 Check_ReleaseFloatArrayElements,
2529 Check_ReleaseDoubleArrayElements,
2531 Check_GetBooleanArrayRegion,
2532 Check_GetByteArrayRegion,
2533 Check_GetCharArrayRegion,
2534 Check_GetShortArrayRegion,
2535 Check_GetIntArrayRegion,
2536 Check_GetLongArrayRegion,
2537 Check_GetFloatArrayRegion,
2538 Check_GetDoubleArrayRegion,
2539 Check_SetBooleanArrayRegion,
2540 Check_SetByteArrayRegion,
2541 Check_SetCharArrayRegion,
2542 Check_SetShortArrayRegion,
2543 Check_SetIntArrayRegion,
2544 Check_SetLongArrayRegion,
2545 Check_SetFloatArrayRegion,
2546 Check_SetDoubleArrayRegion,
2548 Check_RegisterNatives,
2549 Check_UnregisterNatives,
2556 Check_GetStringRegion,
2557 Check_GetStringUTFRegion,
2559 Check_GetPrimitiveArrayCritical,
2560 Check_ReleasePrimitiveArrayCritical,
2562 Check_GetStringCritical,
2563 Check_ReleaseStringCritical,
2565 Check_NewWeakGlobalRef,
2566 Check_DeleteWeakGlobalRef,
2568 Check_ExceptionCheck,
2570 Check_NewDirectByteBuffer,
2571 Check_GetDirectBufferAddress,
2572 Check_GetDirectBufferCapacity,
2574 Check_GetObjectRefType
2576 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2581 Check_DestroyJavaVM,
2582 Check_AttachCurrentThread,
2583 Check_DetachCurrentThread,
2587 Check_AttachCurrentThreadAsDaemon,
2592 * Replace the normal table with the checked table.
2594 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2596 assert(pEnv->funcTable != &gCheckNativeInterface);
2597 pEnv->baseFuncTable = pEnv->funcTable;
2598 pEnv->funcTable = &gCheckNativeInterface;
2602 * Replace the normal table with the checked table.
2604 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2606 assert(pVm->funcTable != &gCheckInvokeInterface);
2607 pVm->baseFuncTable = pVm->funcTable;
2608 pVm->funcTable = &gCheckInvokeInterface;