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 checkCallResultCommon(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). However, the current class loader may
89 * not be listed as an initiating loader, so we can't just look for
90 * it in the loaded-classes list.
92 ClassObject* declClazz;
94 declClazz = dvmFindClassNoInit(declType, method->clazz->classLoader);
95 if (declClazz == NULL) {
96 LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
98 LOGW(" failed in %s.%s ('%s' not found)\n",
99 method->clazz->descriptor, method->name, declType);
103 if (!dvmInstanceof(objClazz, declClazz)) {
104 LOGW("JNI WARNING: method declared to return '%s' returned '%s'\n",
106 LOGW(" failed in %s.%s\n",
107 method->clazz->descriptor, method->name);
111 LOGV("Check %s.%s: %s io %s (SLOW-OK)\n",
112 method->clazz->descriptor, method->name, objType, declType);
118 * Determine if we need to check the return type coming out of the call.
120 * (We don't do this at the top of checkCallResultCommon() because this is on
121 * the critical path for native method calls.)
123 static inline bool callNeedsCheck(const u4* args, JValue* pResult,
124 const Method* method, Thread* self)
126 return (method->shorty[0] == 'L' && !dvmCheckException(self) &&
131 * Check a call into native code.
133 void dvmCheckCallJNIMethod_general(const u4* args, JValue* pResult,
134 const Method* method, Thread* self)
136 dvmCallJNIMethod_general(args, pResult, method, self);
137 if (callNeedsCheck(args, pResult, method, self))
138 checkCallResultCommon(args, pResult, method, self);
142 * Check a synchronized call into native code.
144 void dvmCheckCallJNIMethod_synchronized(const u4* args, JValue* pResult,
145 const Method* method, Thread* self)
147 dvmCallJNIMethod_synchronized(args, pResult, method, self);
148 if (callNeedsCheck(args, pResult, method, self))
149 checkCallResultCommon(args, pResult, method, self);
153 * Check a virtual call with no reference arguments (other than "this").
155 void dvmCheckCallJNIMethod_virtualNoRef(const u4* args, JValue* pResult,
156 const Method* method, Thread* self)
158 dvmCallJNIMethod_virtualNoRef(args, pResult, method, self);
159 if (callNeedsCheck(args, pResult, method, self))
160 checkCallResultCommon(args, pResult, method, self);
164 * Check a static call with no reference arguments (other than "clazz").
166 void dvmCheckCallJNIMethod_staticNoRef(const u4* args, JValue* pResult,
167 const Method* method, Thread* self)
169 dvmCallJNIMethod_staticNoRef(args, pResult, method, self);
170 if (callNeedsCheck(args, pResult, method, self))
171 checkCallResultCommon(args, pResult, method, self);
176 * ===========================================================================
177 * JNI function helpers
178 * ===========================================================================
181 #define JNI_ENTER() dvmChangeStatus(NULL, THREAD_RUNNING)
182 #define JNI_EXIT() dvmChangeStatus(NULL, THREAD_NATIVE)
184 #define BASE_ENV(_env) (((JNIEnvExt*)_env)->baseFuncTable)
185 #define BASE_VM(_vm) (((JavaVMExt*)_vm)->baseFuncTable)
187 #define kRedundantDirectBufferTest false
190 * Flags passed into checkThread().
192 #define kFlag_Default 0x0000
194 #define kFlag_CritBad 0x0000 /* calling while in critical is bad */
195 #define kFlag_CritOkay 0x0001 /* ...okay */
196 #define kFlag_CritGet 0x0002 /* this is a critical "get" */
197 #define kFlag_CritRelease 0x0003 /* this is a critical "release" */
198 #define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
200 #define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
201 #define kFlag_ExcepOkay 0x0004 /* ...okay */
204 * Enter/exit macros for JNI env "check" functions. These do not change
205 * the thread state within the VM.
207 #define CHECK_ENTER(_env, _flags) \
209 JNI_TRACE(true, true); \
210 checkThread(_env, _flags, __FUNCTION__); \
213 #define CHECK_EXIT(_env) \
214 do { JNI_TRACE(false, true); } while(false)
218 * Enter/exit macros for JNI invocation interface "check" functions. These
219 * do not change the thread state within the VM.
221 * Set "_hasmeth" to true if we have a valid thread with a method pointer.
222 * We won't have one before attaching a thread, after detaching a thread, or
223 * after destroying the VM.
225 #define CHECK_VMENTER(_vm, _hasmeth) \
226 do { JNI_TRACE(true, _hasmeth); } while(false)
227 #define CHECK_VMEXIT(_vm, _hasmeth) \
228 do { JNI_TRACE(false, _hasmeth); } while(false)
230 #define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic) \
231 checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
232 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid) \
233 checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
234 #define CHECK_CLASS(_env, _clazz) \
235 checkClass(_env, _clazz, __FUNCTION__)
236 #define CHECK_STRING(_env, _str) \
237 checkString(_env, _str, __FUNCTION__)
238 #define CHECK_UTF_STRING(_env, _str, _nullok) \
239 checkUtfString(_env, _str, _nullok, __FUNCTION__)
240 #define CHECK_CLASS_NAME(_env, _str) \
241 checkClassName(_env, _str, __FUNCTION__)
242 #define CHECK_OBJECT(_env, _obj) \
243 checkObject(_env, _obj, __FUNCTION__)
244 #define CHECK_ARRAY(_env, _array) \
245 checkArray(_env, _array, __FUNCTION__)
246 #define CHECK_RELEASE_MODE(_env, _mode) \
247 checkReleaseMode(_env, _mode, __FUNCTION__)
248 #define CHECK_LENGTH_POSITIVE(_env, _length) \
249 checkLengthPositive(_env, _length, __FUNCTION__)
250 #define CHECK_NON_NULL(_env, _ptr) \
251 checkNonNull(_env, _ptr, __FUNCTION__)
252 #define CHECK_SIG(_env, _methid, _sigbyte, _isstatic) \
253 checkSig(_env, _methid, _sigbyte, _isstatic, __FUNCTION__)
254 #define CHECK_METHOD_ARGS_A(_env, _methid, _args) \
255 checkMethodArgsA(_env, _methid, _args, __FUNCTION__)
256 #define CHECK_METHOD_ARGS_V(_env, _methid, _args) \
257 checkMethodArgsV(_env, _methid, _args, __FUNCTION__)
260 * Print trace message when both "checkJNI" and "verbose:jni" are enabled.
262 #define JNI_TRACE(_entry, _hasmeth) \
264 if (gDvm.verboseJni && (_entry)) { \
265 static const char* classDescriptor = "???"; \
266 static const char* methodName = "???"; \
268 const Method* meth = dvmGetCurrentJNIMethod(); \
269 classDescriptor = meth->clazz->descriptor; \
270 methodName = meth->name; \
272 /* use +6 to drop the leading "Check_" */ \
273 LOGI("JNI: %s (from %s.%s)", \
274 (__FUNCTION__)+6, classDescriptor, methodName); \
279 * Log the current location.
281 * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
283 static void showLocation(const Method* meth, const char* func)
285 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
286 LOGW(" in %s.%s %s (%s)\n",
287 meth->clazz->descriptor, meth->name, desc, func + 6);
292 * Abort if we are configured to bail out on JNI warnings.
294 static void abortMaybe(void)
296 JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
298 dvmDumpThread(dvmThreadSelf(), false);
304 * Verify that the current thread is (a) attached and (b) associated with
305 * this particular instance of JNIEnv.
307 * Verify that, if this thread previously made a critical "get" call, we
308 * do the corresponding "release" call before we try anything else.
310 * Verify that, if an exception has been raised, the native code doesn't
311 * make any JNI calls other than the Exception* methods.
313 * TODO? if we add support for non-JNI native calls, make sure that the
314 * method at the top of the interpreted stack is a JNI method call. (Or
315 * set a flag in the Thread/JNIEnv when the call is made and clear it on
318 * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
320 static void checkThread(JNIEnv* env, int flags, const char* func)
322 JNIEnvExt* threadEnv;
323 bool printWarn = false;
324 bool printException = false;
326 /* get the *correct* JNIEnv by going through our TLS pointer */
327 threadEnv = dvmGetJNIEnvForThread();
330 * Verify that the JNIEnv we've been handed matches what we expected
333 if (threadEnv == NULL) {
334 LOGE("JNI ERROR: non-VM thread making JNI calls\n");
335 // don't set printWarn -- it'll try to call showLocation()
337 } else if ((JNIEnvExt*) env != threadEnv) {
338 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
339 LOGE("JNI: threadEnv != thread->env?\n");
343 LOGW("JNI WARNING: threadid=%d using env from threadid=%d\n",
344 threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
347 /* this is a bad idea -- need to throw as we exit, or abort func */
348 //dvmThrowException("Ljava/lang/RuntimeException;",
349 // "invalid use of JNI env ptr");
350 } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
351 /* correct JNIEnv*; make sure the "self" pointer is correct */
352 LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)\n",
353 ((JNIEnvExt*) env)->self, dvmThreadSelf());
358 * Check for critical resource misuse.
360 switch (flags & kFlag_CritMask) {
361 case kFlag_CritOkay: // okay to call this method
363 case kFlag_CritBad: // not okay to call
364 if (threadEnv->critical) {
365 LOGW("JNI WARNING: threadid=%d using JNI after critical get\n",
366 threadEnv->envThreadId);
370 case kFlag_CritGet: // this is a "get" call
371 /* don't check here; we allow nested gets */
372 threadEnv->critical++;
374 case kFlag_CritRelease: // this is a "release" call
375 threadEnv->critical--;
376 if (threadEnv->critical < 0) {
377 LOGW("JNI WARNING: threadid=%d called too many crit releases\n",
378 threadEnv->envThreadId);
387 * Check for raised exceptions.
389 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
390 LOGW("JNI WARNING: JNI method called with exception raised\n");
392 printException = true;
396 showLocation(dvmGetCurrentJNIMethod(), func);
397 if (printException) {
398 LOGW("Pending exception is:\n");
399 dvmLogExceptionStackTrace();
406 * Verify that the field is of the appropriate type. If the field has an
407 * object type, "obj" is the object we're trying to assign into it.
409 * Works for both static and instance fields.
411 static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
412 PrimitiveType prim, bool isStatic, const char* func)
414 static const char* primNameList[] = {
415 "Object/Array", "boolean", "char", "float", "double",
416 "byte", "short", "int", "long", "void"
418 const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
419 Field* field = (Field*) fieldID;
420 bool printWarn = false;
422 if (fieldID == NULL) {
423 LOGE("JNI ERROR: null field ID\n");
427 if (field->signature[0] == 'L' || field->signature[0] == '[') {
428 Object* obj = dvmDecodeIndirectRef(env, jobj);
430 ClassObject* fieldClass =
431 dvmFindLoadedClass(field->signature);
432 ClassObject* objClass = obj->clazz;
434 assert(fieldClass != NULL);
435 assert(objClass != NULL);
437 if (!dvmInstanceof(objClass, fieldClass)) {
438 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
439 field->name, field->signature, objClass->descriptor);
443 } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
444 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)\n",
445 field->name, field->signature, primNames[prim]);
447 } else if (isStatic && !dvmIsStaticField(field)) {
449 LOGW("JNI WARNING: accessing non-static field %s as static\n",
452 LOGW("JNI WARNING: accessing static field %s as non-static\n",
458 showLocation(dvmGetCurrentJNIMethod(), func);
464 * Verify that "jobj" is a valid object, and that it's an object that JNI
465 * is allowed to know about. We allow NULL references.
467 * Must be in "running" mode before calling here.
469 static void checkObject0(JNIEnv* env, jobject jobj, const char* func)
471 UNUSED_PARAMETER(env);
472 bool printWarn = false;
477 if (dvmIsWeakGlobalRef(jobj)) {
479 * Normalize and continue. This will tell us if the PhantomReference
482 jobj = dvmNormalizeWeakGlobalRef((jweak) jobj);
485 if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
486 LOGW("JNI WARNING: %p is not a valid JNI reference\n", jobj);
489 Object* obj = dvmDecodeIndirectRef(env, jobj);
491 if (obj == NULL || !dvmIsValidObject(obj)) {
492 LOGW("JNI WARNING: native code passing in bad object %p %p (%s)\n",
499 showLocation(dvmGetCurrentJNIMethod(), func);
505 * Verify that "jobj" is a valid object, and that it's an object that JNI
506 * is allowed to know about. We allow NULL references.
508 * Switches to "running" mode before performing checks.
510 static void checkObject(JNIEnv* env, jobject jobj, const char* func)
513 checkObject0(env, jobj, func);
518 * Verify that "clazz" actually points to a class object. (Also performs
521 * We probably don't need to identify where we're being called from,
522 * because the VM is most likely about to crash and leave a core dump
523 * if something is wrong.
525 * Because we're looking at an object on the GC heap, we have to switch
526 * to "running" mode before doing the checks.
528 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
531 bool printWarn = false;
533 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
536 LOGW("JNI WARNING: received null jclass\n");
538 } else if (!dvmIsValidObject((Object*) clazz)) {
539 LOGW("JNI WARNING: jclass points to invalid object %p\n", clazz);
541 } else if (clazz->obj.clazz != gDvm.classJavaLangClass) {
542 LOGW("JNI WARNING: jclass does not point to class object (%p - %s)\n",
543 jclazz, clazz->descriptor);
551 checkObject(env, jclazz, func);
555 * Verify that "str" is non-NULL and points to a String object.
557 * Since we're dealing with objects, switch to "running" mode.
559 static void checkString(JNIEnv* env, jstring jstr, const char* func)
562 bool printWarn = false;
564 Object* obj = dvmDecodeIndirectRef(env, jstr);
567 LOGW("JNI WARNING: received null jstring (%s)\n", func);
569 } else if (obj->clazz != gDvm.classJavaLangString) {
571 * TODO: we probably should test dvmIsValidObject first, because
572 * this will crash if "obj" is non-null but pointing to an invalid
573 * memory region. However, the "is valid" test is a little slow,
574 * we're doing it again over in checkObject().
576 if (dvmIsValidObject(obj))
577 LOGW("JNI WARNING: jstring %p points to non-string object (%s)\n",
580 LOGW("JNI WARNING: jstring %p is bogus (%s)\n", jstr, func);
588 checkObject(env, jstr, func);
592 * Verify that "bytes" points to valid "modified UTF-8" data.
594 static void checkUtfString(JNIEnv* env, const char* bytes, bool nullOk,
597 const char* origBytes = bytes;
601 LOGW("JNI WARNING: unexpectedly null UTF string\n");
608 while (*bytes != '\0') {
609 u1 utf8 = *(bytes++);
610 // Switch on the high four bits.
620 // Bit pattern 0xxx. No need for any extra bytes.
629 * Bit pattern 10xx or 1111, which are illegal start bytes.
630 * Note: 1111 is valid for normal UTF-8, but not the
631 * modified UTF-8 used here.
633 LOGW("JNI WARNING: illegal start byte 0x%x\n", utf8);
637 // Bit pattern 1110, so there are two additional bytes.
639 if ((utf8 & 0xc0) != 0x80) {
640 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
643 // Fall through to take care of the final byte.
647 // Bit pattern 110x, so there is one additional byte.
649 if ((utf8 & 0xc0) != 0x80) {
650 LOGW("JNI WARNING: illegal continuation byte 0x%x\n", utf8);
661 LOGW(" string: '%s'\n", origBytes);
662 showLocation(dvmGetCurrentJNIMethod(), func);
667 * In some circumstances the VM will screen class names, but it doesn't
668 * for class lookup. When things get bounced through a class loader, they
669 * can actually get normalized a couple of times; as a result, passing in
670 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
671 * work in some circumstances.
673 * This is incorrect and could cause strange behavior or compatibility
674 * problems, so we want to screen that out here.
676 * We expect "full-qualified" class names, like "java/lang/Thread" or
677 * "[Ljava/lang/Object;".
679 static void checkClassName(JNIEnv* env, const char* className, const char* func)
683 /* quick check for illegal chars */
685 while (*cp != '\0') {
686 if (*cp == '.') /* catch "java.lang.String" */
690 if (*(cp-1) == ';' && *className == 'L')
691 goto fail; /* catch "Ljava/lang/String;" */
693 // TODO: need a more rigorous check here
698 LOGW("JNI WARNING: illegal class name '%s' (%s)\n", className, func);
699 LOGW(" (should be formed like 'java/lang/String')\n");
704 * Verify that "array" is non-NULL and points to an Array object.
706 * Since we're dealing with objects, switch to "running" mode.
708 static void checkArray(JNIEnv* env, jarray jarr, const char* func)
711 bool printWarn = false;
713 Object* obj = dvmDecodeIndirectRef(env, jarr);
716 LOGW("JNI WARNING: received null array (%s)\n", func);
718 } else if (obj->clazz->descriptor[0] != '[') {
719 if (dvmIsValidObject(obj))
720 LOGW("JNI WARNING: jarray %p points to non-array object (%s)\n",
721 jarr, obj->clazz->descriptor);
723 LOGW("JNI WARNING: jarray %p is bogus\n", jarr);
732 checkObject(env, jarr, func);
736 * Verify that the "mode" argument passed to a primitive array Release
737 * function is one of the valid values.
739 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
741 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
742 LOGW("JNI WARNING: bad value for mode (%d) (%s)\n", mode, func);
748 * Verify that the length argument to array-creation calls is >= 0.
750 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
753 LOGW("JNI WARNING: negative length for array allocation (%s)\n", func);
759 * Verify that the pointer value is non-NULL.
761 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
764 LOGW("JNI WARNING: invalid null pointer (%s)\n", func);
770 * Verify that the method's return type matches the type of call.
772 * "expectedSigByte" will be 'L' for all objects, including arrays.
774 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
775 bool isStatic, const char* func)
777 const Method* meth = (const Method*) methodID;
778 bool printWarn = false;
780 if (expectedSigByte != meth->shorty[0]) {
781 LOGW("JNI WARNING: expected return type '%c'\n", expectedSigByte);
783 } else if (isStatic && !dvmIsStaticMethod(meth)) {
785 LOGW("JNI WARNING: calling non-static method with static call\n");
787 LOGW("JNI WARNING: calling static method with non-static call\n");
792 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
793 LOGW(" calling %s.%s %s\n",
794 meth->clazz->descriptor, meth->name, desc);
796 showLocation(dvmGetCurrentJNIMethod(), func);
802 * Verify that this static field ID is valid for this class.
804 static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
806 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
807 StaticField* base = &clazz->sfields[0];
808 int fieldCount = clazz->sfieldCount;
810 if ((StaticField*) fieldID < base ||
811 (StaticField*) fieldID >= base + fieldCount)
813 LOGW("JNI WARNING: static fieldID %p not valid for class %s\n",
814 fieldID, clazz->descriptor);
815 LOGW(" base=%p count=%d\n", base, fieldCount);
821 * Verify that this instance field ID is valid for this object.
823 static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
829 LOGW("JNI WARNING: invalid null object (%s)\n", func);
834 Object* obj = dvmDecodeIndirectRef(env, jobj);
835 ClassObject* clazz = obj->clazz;
838 * Check this class and all of its superclasses for a matching field.
839 * Don't need to scan interfaces.
841 while (clazz != NULL) {
842 if ((InstField*) fieldID >= clazz->ifields &&
843 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
848 clazz = clazz->super;
851 LOGW("JNI WARNING: inst fieldID %p not valid for class %s\n",
852 fieldID, obj->clazz->descriptor);
860 * Verify that the reference arguments being passed in are appropriate for
863 * At a minimum we want to make sure that the argument is a valid
864 * reference. We can also do a class lookup on the method signature
865 * and verify that the object is an instance of the appropriate class,
866 * but that's more expensive.
868 * The basic tests are redundant when indirect references are enabled,
869 * since reference arguments must always be converted explicitly. An
870 * instanceof test would not be redundant, but we're not doing that at
873 static void checkMethodArgsV(JNIEnv* env, jmethodID methodID, va_list args,
876 #ifndef USE_INDIRECT_REF
879 const Method* meth = (const Method*) methodID;
880 const char* desc = meth->shorty;
883 LOGV("V-checking %s.%s:%s...\n", meth->clazz->descriptor, meth->name, desc);
885 while (*++desc != '\0') { /* pre-incr to skip return type */
888 { /* 'shorty' descr uses L for all refs, incl array */
889 jobject argObj = va_arg(args, jobject);
890 checkObject0(env, argObj, func);
893 case 'D': /* 8-byte double */
894 case 'J': /* 8-byte long */
895 case 'F': /* floats normalized to doubles */
896 (void) va_arg(args, u8);
898 default: /* Z B C S I -- all passed as 32-bit integers */
899 (void) va_arg(args, u4);
910 * Same purpose as checkMethodArgsV, but with arguments in an array of
913 static void checkMethodArgsA(JNIEnv* env, jmethodID methodID, jvalue* args,
916 #ifndef USE_INDIRECT_REF
919 const Method* meth = (const Method*) methodID;
920 const char* desc = meth->shorty;
924 LOGV("A-checking %s.%s:%s...\n", meth->clazz->descriptor, meth->name, desc);
926 while (*++desc != '\0') { /* pre-incr to skip return type */
928 jobject argObj = args[idx].l;
929 checkObject0(env, argObj, func);
942 * ===========================================================================
944 * ===========================================================================
947 #define kGuardLen 512 /* must be multiple of 2 */
948 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
949 #define kGuardMagic 0xffd5aa96
950 #define kGuardExtra sizeof(GuardExtra)
952 /* this gets tucked in at the start of the buffer; struct size must be even */
953 typedef struct GuardExtra {
957 const void* originalPtr;
960 /* find the GuardExtra given the pointer into the "live" data */
961 inline static GuardExtra* getGuardExtra(const void* dataBuf)
963 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
964 return (GuardExtra*) fullBuf;
968 * Create an oversized buffer to hold the contents of "buf". Copy it in,
969 * filling in the area around it with guard data.
971 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
973 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
976 size_t newLen = (len + kGuardLen +1) & ~0x01;
981 newBuf = (u1*)malloc(newLen);
982 if (newBuf == NULL) {
983 LOGE("createGuardedCopy failed on alloc of %d bytes\n", newLen);
987 /* fill it in with a pattern */
989 for (i = 0; i < (int)newLen / 2; i++)
990 *pat++ = kGuardPattern;
992 /* copy the data in; note "len" could be zero */
993 memcpy(newBuf + kGuardLen / 2, buf, len);
995 /* if modification is not expected, grab a checksum */
998 adler = adler32(0L, Z_NULL, 0);
999 adler = adler32(adler, buf, len);
1000 *(uLong*)newBuf = adler;
1003 pExtra = (GuardExtra*) newBuf;
1004 pExtra->magic = kGuardMagic;
1005 pExtra->adler = adler;
1006 pExtra->originalPtr = buf;
1007 pExtra->originalLen = len;
1009 return newBuf + kGuardLen / 2;
1013 * Verify the guard area and, if "modOkay" is false, that the data itself
1014 * has not been altered.
1016 * The caller has already checked that "dataBuf" is non-NULL.
1018 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
1020 static const u4 kMagicCmp = kGuardMagic;
1021 const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
1022 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1028 * Before we do anything with "pExtra", check the magic number. We
1029 * do the check with memcmp rather than "==" in case the pointer is
1030 * unaligned. If it points to completely bogus memory we're going
1031 * to crash, but there's no easy way around that.
1033 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
1035 memcpy(buf, &pExtra->magic, 4);
1036 LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
1037 "-- incorrect data pointer %p?\n",
1038 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
1042 len = pExtra->originalLen;
1044 /* check bottom half of guard; skip over optional checksum storage */
1045 pat = (u2*) fullBuf;
1046 for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
1048 if (pat[i] != kGuardPattern) {
1049 LOGE("JNI: guard pattern(1) disturbed at %p + %d\n",
1055 int offset = kGuardLen / 2 + len;
1056 if (offset & 0x01) {
1057 /* odd byte; expected value depends on endian-ness of host */
1058 const u2 patSample = kGuardPattern;
1059 if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
1060 LOGE("JNI: guard pattern disturbed in odd byte after %p "
1061 "(+%d) 0x%02x 0x%02x\n",
1062 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
1068 /* check top half of guard */
1069 pat = (u2*) (fullBuf + offset);
1070 for (i = 0; i < kGuardLen / 4; i++) {
1071 if (pat[i] != kGuardPattern) {
1072 LOGE("JNI: guard pattern(2) disturbed at %p + %d\n",
1073 fullBuf, offset + i*2);
1079 * If modification is not expected, verify checksum. Strictly speaking
1080 * this is wrong: if we told the client that we made a copy, there's no
1081 * reason they can't alter the buffer.
1084 uLong adler = adler32(0L, Z_NULL, 0);
1085 adler = adler32(adler, dataBuf, len);
1086 if (pExtra->adler != adler) {
1087 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p\n",
1088 pExtra->adler, adler, dataBuf);
1097 * Free up the guard buffer, scrub it, and return the original pointer.
1099 static void* freeGuardedCopy(void* dataBuf)
1101 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
1102 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1103 void* originalPtr = (void*) pExtra->originalPtr;
1104 size_t len = pExtra->originalLen;
1106 memset(dataBuf, 0xdd, len);
1112 * Just pull out the original pointer.
1114 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
1116 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1117 return (void*) pExtra->originalPtr;
1121 * Grab the data length.
1123 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
1125 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1126 return pExtra->originalLen;
1130 * Return the width, in bytes, of a primitive type.
1132 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
1134 static const int lengths[PRIM_MAX] = {
1145 assert(primType >= 0 && primType < PRIM_MAX);
1146 return lengths[primType];
1150 * Create a guarded copy of a primitive array. Modifications to the copied
1151 * data are allowed. Returns a pointer to the copied data.
1153 static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
1156 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1157 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1158 int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1161 result = createGuardedCopy(arrObj->contents, len, true);
1170 * Perform the array "release" operation, which may or may not copy data
1171 * back into the VM, and may or may not release the underlying storage.
1173 static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
1176 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1177 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1178 //int len = array->length * dvmPrimitiveTypeWidth(primType);
1179 bool release, copyBack;
1182 if (!checkGuardedCopy(dataBuf, true)) {
1183 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy\n");
1190 release = copyBack = true;
1201 LOGE("JNI: bad release mode %d\n", mode);
1207 size_t len = getGuardedCopyOriginalLen(dataBuf);
1208 memcpy(arrObj->contents, dataBuf, len);
1212 result = (u1*) freeGuardedCopy(dataBuf);
1214 result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
1217 /* pointer is to the array contents; back up to the array object */
1218 result -= offsetof(ArrayObject, contents);
1225 * ===========================================================================
1227 * ===========================================================================
1230 static jint Check_GetVersion(JNIEnv* env)
1232 CHECK_ENTER(env, kFlag_Default);
1234 result = BASE_ENV(env)->GetVersion(env);
1239 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1240 const jbyte* buf, jsize bufLen)
1242 CHECK_ENTER(env, kFlag_Default);
1243 CHECK_OBJECT(env, loader);
1244 CHECK_UTF_STRING(env, name, false);
1245 CHECK_CLASS_NAME(env, name);
1247 result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
1252 static jclass Check_FindClass(JNIEnv* env, const char* name)
1254 CHECK_ENTER(env, kFlag_Default);
1255 CHECK_UTF_STRING(env, name, false);
1256 CHECK_CLASS_NAME(env, name);
1258 result = BASE_ENV(env)->FindClass(env, name);
1263 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
1265 CHECK_ENTER(env, kFlag_Default);
1266 CHECK_CLASS(env, clazz);
1268 result = BASE_ENV(env)->GetSuperclass(env, clazz);
1273 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1276 CHECK_ENTER(env, kFlag_Default);
1277 CHECK_CLASS(env, clazz1);
1278 CHECK_CLASS(env, clazz2);
1280 result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1285 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1287 CHECK_ENTER(env, kFlag_Default);
1288 CHECK_OBJECT(env, method);
1290 result = BASE_ENV(env)->FromReflectedMethod(env, method);
1295 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1297 CHECK_ENTER(env, kFlag_Default);
1298 CHECK_OBJECT(env, field);
1300 result = BASE_ENV(env)->FromReflectedField(env, field);
1305 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1306 jmethodID methodID, jboolean isStatic)
1308 CHECK_ENTER(env, kFlag_Default);
1309 CHECK_CLASS(env, cls);
1311 result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1316 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1319 CHECK_ENTER(env, kFlag_Default);
1320 CHECK_CLASS(env, cls);
1322 result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1327 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1329 CHECK_ENTER(env, kFlag_Default);
1330 CHECK_OBJECT(env, obj);
1332 result = BASE_ENV(env)->Throw(env, obj);
1337 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1339 CHECK_ENTER(env, kFlag_Default);
1340 CHECK_CLASS(env, clazz);
1341 CHECK_UTF_STRING(env, message, true);
1343 result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1348 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1350 CHECK_ENTER(env, kFlag_ExcepOkay);
1352 result = BASE_ENV(env)->ExceptionOccurred(env);
1357 static void Check_ExceptionDescribe(JNIEnv* env)
1359 CHECK_ENTER(env, kFlag_ExcepOkay);
1360 BASE_ENV(env)->ExceptionDescribe(env);
1364 static void Check_ExceptionClear(JNIEnv* env)
1366 CHECK_ENTER(env, kFlag_ExcepOkay);
1367 BASE_ENV(env)->ExceptionClear(env);
1371 static void Check_FatalError(JNIEnv* env, const char* msg)
1373 CHECK_ENTER(env, kFlag_Default);
1374 CHECK_UTF_STRING(env, msg, true);
1375 BASE_ENV(env)->FatalError(env, msg);
1379 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1381 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1383 result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1388 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1390 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1391 CHECK_OBJECT(env, res);
1393 result = BASE_ENV(env)->PopLocalFrame(env, res);
1398 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1400 CHECK_ENTER(env, kFlag_Default);
1401 CHECK_OBJECT(env, obj);
1403 result = BASE_ENV(env)->NewGlobalRef(env, obj);
1408 static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
1410 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1411 CHECK_OBJECT(env, globalRef);
1412 #ifdef USE_INDIRECT_REF
1413 if (globalRef != NULL &&
1414 dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
1416 LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)\n",
1417 globalRef, dvmGetJNIRefType(env, globalRef));
1422 BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
1427 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1429 CHECK_ENTER(env, kFlag_Default);
1430 CHECK_OBJECT(env, ref);
1432 result = BASE_ENV(env)->NewLocalRef(env, ref);
1437 static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
1439 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1440 CHECK_OBJECT(env, localRef);
1441 #ifdef USE_INDIRECT_REF
1442 if (localRef != NULL &&
1443 dvmGetJNIRefType(env, localRef) != JNILocalRefType)
1445 LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)\n",
1446 localRef, dvmGetJNIRefType(env, localRef));
1451 BASE_ENV(env)->DeleteLocalRef(env, localRef);
1456 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1458 CHECK_ENTER(env, kFlag_Default);
1460 result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1465 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1467 CHECK_ENTER(env, kFlag_Default);
1468 CHECK_OBJECT(env, ref1);
1469 CHECK_OBJECT(env, ref2);
1471 result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1476 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1478 CHECK_ENTER(env, kFlag_Default);
1479 CHECK_CLASS(env, clazz);
1481 result = BASE_ENV(env)->AllocObject(env, clazz);
1486 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1489 CHECK_ENTER(env, kFlag_Default);
1490 CHECK_CLASS(env, clazz);
1492 va_list args, tmpArgs;
1494 va_start(args, methodID);
1496 va_copy(tmpArgs, args);
1497 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);
1500 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1506 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1509 CHECK_ENTER(env, kFlag_Default);
1510 CHECK_CLASS(env, clazz);
1514 va_copy(tmpArgs, args);
1515 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);
1518 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1522 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1525 CHECK_ENTER(env, kFlag_Default);
1526 CHECK_CLASS(env, clazz);
1529 CHECK_METHOD_ARGS_A(env, methodID, args);
1530 result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1535 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1537 CHECK_ENTER(env, kFlag_Default);
1538 CHECK_OBJECT(env, obj);
1540 result = BASE_ENV(env)->GetObjectClass(env, obj);
1545 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1547 CHECK_ENTER(env, kFlag_Default);
1548 CHECK_OBJECT(env, obj);
1549 CHECK_CLASS(env, clazz);
1551 result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1556 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1559 CHECK_ENTER(env, kFlag_Default);
1560 CHECK_CLASS(env, clazz);
1561 CHECK_UTF_STRING(env, name, false);
1562 CHECK_UTF_STRING(env, sig, false);
1564 result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1569 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1570 const char* name, const char* sig)
1572 CHECK_ENTER(env, kFlag_Default);
1573 CHECK_CLASS(env, clazz);
1574 CHECK_UTF_STRING(env, name, false);
1575 CHECK_UTF_STRING(env, sig, false);
1577 result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1582 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1583 const char* name, const char* sig)
1585 CHECK_ENTER(env, kFlag_Default);
1586 CHECK_CLASS(env, clazz);
1587 CHECK_UTF_STRING(env, name, false);
1588 CHECK_UTF_STRING(env, sig, false);
1590 result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1595 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1596 const char* name, const char* sig)
1598 CHECK_ENTER(env, kFlag_Default);
1599 CHECK_CLASS(env, clazz);
1600 CHECK_UTF_STRING(env, name, false);
1601 CHECK_UTF_STRING(env, sig, false);
1603 result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1608 #define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
1609 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1612 CHECK_ENTER(env, kFlag_Default); \
1613 CHECK_CLASS(env, clazz); \
1615 checkStaticFieldID(env, clazz, fieldID); \
1616 result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
1621 GET_STATIC_TYPE_FIELD(jobject, Object);
1622 GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1623 GET_STATIC_TYPE_FIELD(jbyte, Byte);
1624 GET_STATIC_TYPE_FIELD(jchar, Char);
1625 GET_STATIC_TYPE_FIELD(jshort, Short);
1626 GET_STATIC_TYPE_FIELD(jint, Int);
1627 GET_STATIC_TYPE_FIELD(jlong, Long);
1628 GET_STATIC_TYPE_FIELD(jfloat, Float);
1629 GET_STATIC_TYPE_FIELD(jdouble, Double);
1631 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1632 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1633 jfieldID fieldID, _ctype value) \
1635 CHECK_ENTER(env, kFlag_Default); \
1636 CHECK_CLASS(env, clazz); \
1637 checkStaticFieldID(env, clazz, fieldID); \
1638 /* "value" arg only used when type == ref */ \
1639 CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true); \
1640 BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
1644 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1645 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1646 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1647 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1648 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1649 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1650 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1651 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1652 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1654 #define GET_TYPE_FIELD(_ctype, _jname) \
1655 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
1658 CHECK_ENTER(env, kFlag_Default); \
1659 CHECK_OBJECT(env, obj); \
1661 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1662 result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
1666 GET_TYPE_FIELD(jobject, Object);
1667 GET_TYPE_FIELD(jboolean, Boolean);
1668 GET_TYPE_FIELD(jbyte, Byte);
1669 GET_TYPE_FIELD(jchar, Char);
1670 GET_TYPE_FIELD(jshort, Short);
1671 GET_TYPE_FIELD(jint, Int);
1672 GET_TYPE_FIELD(jlong, Long);
1673 GET_TYPE_FIELD(jfloat, Float);
1674 GET_TYPE_FIELD(jdouble, Double);
1676 #define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1677 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
1678 jfieldID fieldID, _ctype value) \
1680 CHECK_ENTER(env, kFlag_Default); \
1681 CHECK_OBJECT(env, obj); \
1682 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1683 /* "value" arg only used when type == ref */ \
1684 CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
1685 BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
1688 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1689 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1690 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1691 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1692 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1693 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1694 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1695 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1696 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1698 #define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1699 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
1700 jmethodID methodID, ...) \
1702 CHECK_ENTER(env, kFlag_Default); \
1703 CHECK_OBJECT(env, obj); \
1704 CHECK_SIG(env, methodID, _retsig, false); \
1706 va_list args, tmpArgs; \
1707 va_start(args, methodID); \
1708 va_copy(tmpArgs, args); \
1709 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1711 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1717 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1718 jmethodID methodID, va_list args) \
1720 CHECK_ENTER(env, kFlag_Default); \
1721 CHECK_OBJECT(env, obj); \
1722 CHECK_SIG(env, methodID, _retsig, false); \
1725 va_copy(tmpArgs, args); \
1726 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1728 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1733 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1734 jmethodID methodID, jvalue* args) \
1736 CHECK_ENTER(env, kFlag_Default); \
1737 CHECK_OBJECT(env, obj); \
1738 CHECK_SIG(env, methodID, _retsig, false); \
1740 CHECK_METHOD_ARGS_A(env, methodID, args); \
1741 _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
1746 CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1747 CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1748 CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1749 CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1750 CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1751 CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
1752 CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1753 CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1754 CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1755 CALL_VIRTUAL(void, Void, , , , 'V');
1757 #define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \
1759 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
1760 jobject obj, jclass clazz, jmethodID methodID, ...) \
1762 CHECK_ENTER(env, kFlag_Default); \
1763 CHECK_CLASS(env, clazz); \
1764 CHECK_OBJECT(env, obj); \
1765 CHECK_SIG(env, methodID, _retsig, false); \
1767 va_list args, tmpArgs; \
1768 va_start(args, methodID); \
1769 va_copy(tmpArgs, args); \
1770 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1772 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1773 clazz, methodID, args); \
1778 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1779 jobject obj, jclass clazz, jmethodID methodID, va_list args) \
1781 CHECK_ENTER(env, kFlag_Default); \
1782 CHECK_CLASS(env, clazz); \
1783 CHECK_OBJECT(env, obj); \
1784 CHECK_SIG(env, methodID, _retsig, false); \
1787 va_copy(tmpArgs, args); \
1788 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1790 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1791 clazz, methodID, args); \
1795 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1796 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
1798 CHECK_ENTER(env, kFlag_Default); \
1799 CHECK_CLASS(env, clazz); \
1800 CHECK_OBJECT(env, obj); \
1801 CHECK_SIG(env, methodID, _retsig, false); \
1803 CHECK_METHOD_ARGS_A(env, methodID, args); \
1804 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
1805 clazz, methodID, args); \
1809 CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1810 CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1811 CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1812 CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1813 CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1814 CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
1815 CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1816 CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1817 CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1818 CALL_NONVIRTUAL(void, Void, , , , 'V');
1821 #define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1822 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
1823 jclass clazz, jmethodID methodID, ...) \
1825 CHECK_ENTER(env, kFlag_Default); \
1826 CHECK_CLASS(env, clazz); \
1827 CHECK_SIG(env, methodID, _retsig, true); \
1829 va_list args, tmpArgs; \
1830 va_start(args, methodID); \
1831 va_copy(tmpArgs, args); \
1832 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1834 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1840 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
1841 jclass clazz, jmethodID methodID, va_list args) \
1843 CHECK_ENTER(env, kFlag_Default); \
1844 CHECK_CLASS(env, clazz); \
1845 CHECK_SIG(env, methodID, _retsig, true); \
1848 va_copy(tmpArgs, args); \
1849 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1851 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1856 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
1857 jclass clazz, jmethodID methodID, jvalue* args) \
1859 CHECK_ENTER(env, kFlag_Default); \
1860 CHECK_CLASS(env, clazz); \
1861 CHECK_SIG(env, methodID, _retsig, true); \
1863 CHECK_METHOD_ARGS_A(env, methodID, args); \
1864 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
1869 CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
1870 CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
1871 CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
1872 CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
1873 CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
1874 CALL_STATIC(jint, Int, jint result, result=, result, 'I');
1875 CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
1876 CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
1877 CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
1878 CALL_STATIC(void, Void, , , , 'V');
1880 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1883 CHECK_ENTER(env, kFlag_Default);
1885 result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1890 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1892 CHECK_ENTER(env, kFlag_CritOkay);
1893 CHECK_STRING(env, string);
1895 result = BASE_ENV(env)->GetStringLength(env, string);
1900 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1903 CHECK_ENTER(env, kFlag_CritOkay);
1904 CHECK_STRING(env, string);
1905 const jchar* result;
1906 result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1907 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1908 // TODO: fix for indirect
1909 int len = dvmStringLen(string) * 2;
1910 result = (const jchar*) createGuardedCopy(result, len, false);
1918 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1921 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1922 CHECK_STRING(env, string);
1923 CHECK_NON_NULL(env, chars);
1924 if (((JNIEnvExt*)env)->forceDataCopy) {
1925 if (!checkGuardedCopy(chars, false)) {
1926 LOGE("JNI: failed guarded copy check in ReleaseStringChars\n");
1930 chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1932 BASE_ENV(env)->ReleaseStringChars(env, string, chars);
1936 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
1938 CHECK_ENTER(env, kFlag_Default);
1939 CHECK_UTF_STRING(env, bytes, true);
1941 result = BASE_ENV(env)->NewStringUTF(env, bytes);
1946 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
1948 CHECK_ENTER(env, kFlag_CritOkay);
1949 CHECK_STRING(env, string);
1951 result = BASE_ENV(env)->GetStringUTFLength(env, string);
1956 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
1959 CHECK_ENTER(env, kFlag_CritOkay);
1960 CHECK_STRING(env, string);
1962 result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
1963 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1964 // TODO: fix for indirect
1965 int len = dvmStringUtf8ByteLen(string) + 1;
1966 result = (const char*) createGuardedCopy(result, len, false);
1974 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
1977 CHECK_ENTER(env, kFlag_ExcepOkay);
1978 CHECK_STRING(env, string);
1979 CHECK_NON_NULL(env, utf);
1980 if (((JNIEnvExt*)env)->forceDataCopy) {
1981 //int len = dvmStringUtf8ByteLen(string) + 1;
1982 if (!checkGuardedCopy(utf, false)) {
1983 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars\n");
1987 utf = (const char*) freeGuardedCopy((char*)utf);
1989 BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
1993 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
1995 CHECK_ENTER(env, kFlag_CritOkay);
1996 CHECK_ARRAY(env, array);
1998 result = BASE_ENV(env)->GetArrayLength(env, array);
2003 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
2004 jclass elementClass, jobject initialElement)
2006 CHECK_ENTER(env, kFlag_Default);
2007 CHECK_CLASS(env, elementClass);
2008 CHECK_OBJECT(env, initialElement);
2009 CHECK_LENGTH_POSITIVE(env, length);
2010 jobjectArray result;
2011 result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
2017 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
2020 CHECK_ENTER(env, kFlag_Default);
2021 CHECK_ARRAY(env, array);
2023 result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
2028 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
2029 jsize index, jobject value)
2031 CHECK_ENTER(env, kFlag_Default);
2032 CHECK_ARRAY(env, array);
2033 BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
2037 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
2038 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
2040 CHECK_ENTER(env, kFlag_Default); \
2041 CHECK_LENGTH_POSITIVE(env, length); \
2043 result = BASE_ENV(env)->New##_jname##Array(env, length); \
2047 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
2048 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
2049 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
2050 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
2051 NEW_PRIMITIVE_ARRAY(jintArray, Int);
2052 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
2053 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
2054 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
2057 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
2058 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
2059 _ctype##Array array, jboolean* isCopy) \
2061 CHECK_ENTER(env, kFlag_Default); \
2062 CHECK_ARRAY(env, array); \
2064 result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
2066 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
2067 result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
2073 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
2074 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
2075 _ctype##Array array, _ctype* elems, jint mode) \
2077 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
2078 CHECK_ARRAY(env, array); \
2079 CHECK_NON_NULL(env, elems); \
2080 CHECK_RELEASE_MODE(env, mode); \
2081 if (((JNIEnvExt*)env)->forceDataCopy) { \
2082 elems = (_ctype*) releaseGuardedPACopy(env, array, elems, mode);\
2084 BASE_ENV(env)->Release##_jname##ArrayElements(env, \
2085 array, elems, mode); \
2089 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
2090 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
2091 _ctype##Array array, jsize start, jsize len, _ctype* buf) \
2093 CHECK_ENTER(env, kFlag_Default); \
2094 CHECK_ARRAY(env, array); \
2095 BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
2100 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
2101 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
2102 _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
2104 CHECK_ENTER(env, kFlag_Default); \
2105 CHECK_ARRAY(env, array); \
2106 BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
2111 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
2112 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
2113 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
2114 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
2115 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
2117 /* TODO: verify primitive array type matches call type */
2118 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
2119 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
2120 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
2121 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
2122 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
2123 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
2124 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
2125 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
2127 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
2128 const JNINativeMethod* methods, jint nMethods)
2130 CHECK_ENTER(env, kFlag_Default);
2131 CHECK_CLASS(env, clazz);
2133 result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
2138 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
2140 CHECK_ENTER(env, kFlag_Default);
2141 CHECK_CLASS(env, clazz);
2143 result = BASE_ENV(env)->UnregisterNatives(env, clazz);
2148 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
2150 CHECK_ENTER(env, kFlag_Default);
2151 CHECK_OBJECT(env, obj);
2153 result = BASE_ENV(env)->MonitorEnter(env, obj);
2158 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
2160 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2161 CHECK_OBJECT(env, obj);
2163 result = BASE_ENV(env)->MonitorExit(env, obj);
2168 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
2170 CHECK_ENTER(env, kFlag_Default);
2172 result = BASE_ENV(env)->GetJavaVM(env, vm);
2177 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
2178 jsize len, jchar* buf)
2180 CHECK_ENTER(env, kFlag_CritOkay);
2181 CHECK_STRING(env, str);
2182 BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
2186 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
2187 jsize len, char* buf)
2189 CHECK_ENTER(env, kFlag_CritOkay);
2190 CHECK_STRING(env, str);
2191 BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
2195 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
2198 CHECK_ENTER(env, kFlag_CritGet);
2199 CHECK_ARRAY(env, array);
2201 result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
2202 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2203 result = createGuardedPACopy(env, array, isCopy);
2209 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
2210 void* carray, jint mode)
2212 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2213 CHECK_ARRAY(env, array);
2214 CHECK_NON_NULL(env, carray);
2215 CHECK_RELEASE_MODE(env, mode);
2216 if (((JNIEnvExt*)env)->forceDataCopy) {
2217 carray = releaseGuardedPACopy(env, array, carray, mode);
2219 BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2223 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
2226 CHECK_ENTER(env, kFlag_CritGet);
2227 CHECK_STRING(env, string);
2228 const jchar* result;
2229 result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
2230 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2231 // TODO: fix for indirect
2232 int len = dvmStringLen(string) * 2;
2233 result = (const jchar*) createGuardedCopy(result, len, false);
2241 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
2242 const jchar* carray)
2244 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2245 CHECK_STRING(env, string);
2246 CHECK_NON_NULL(env, carray);
2247 if (((JNIEnvExt*)env)->forceDataCopy) {
2248 if (!checkGuardedCopy(carray, false)) {
2249 LOGE("JNI: failed guarded copy check in ReleaseStringCritical\n");
2253 carray = (const jchar*) freeGuardedCopy((jchar*)carray);
2255 BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
2259 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
2261 CHECK_ENTER(env, kFlag_Default);
2262 CHECK_OBJECT(env, obj);
2264 result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
2269 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
2271 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2272 CHECK_OBJECT(env, obj);
2273 BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
2277 static jboolean Check_ExceptionCheck(JNIEnv* env)
2279 CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
2281 result = BASE_ENV(env)->ExceptionCheck(env);
2286 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
2288 CHECK_ENTER(env, kFlag_Default);
2289 CHECK_OBJECT(env, obj);
2290 jobjectRefType result;
2291 result = BASE_ENV(env)->GetObjectRefType(env, obj);
2296 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
2299 CHECK_ENTER(env, kFlag_Default);
2301 if (address == NULL || capacity < 0) {
2302 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)\n",
2303 address, (long) capacity);
2307 result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
2312 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
2314 CHECK_ENTER(env, kFlag_Default);
2315 CHECK_OBJECT(env, buf);
2316 void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
2319 /* optional - check result vs. "safe" implementation */
2320 if (kRedundantDirectBufferTest) {
2321 jobject platformAddr = NULL;
2322 void* checkResult = NULL;
2325 * Start by determining if the object supports the DirectBuffer
2326 * interfaces. Note this does not guarantee that it's a direct buffer.
2328 if (JNI_FALSE == (*env)->IsInstanceOf(env, buf,
2329 gDvm.jclassOrgApacheHarmonyNioInternalDirectBuffer))
2335 * Get the PlatformAddress object.
2337 * If this isn't a direct buffer, platformAddr will be NULL and/or an
2338 * exception will have been thrown.
2340 platformAddr = (*env)->CallObjectMethod(env, buf,
2341 (jmethodID) gDvm.methOrgApacheHarmonyNioInternalDirectBuffer_getEffectiveAddress);
2343 if ((*env)->ExceptionCheck(env)) {
2344 (*env)->ExceptionClear(env);
2345 platformAddr = NULL;
2347 if (platformAddr == NULL) {
2348 LOGV("Got request for address of non-direct buffer\n");
2352 jclass platformAddrClass = (*env)->FindClass(env,
2353 "org/apache/harmony/luni/platform/PlatformAddress");
2354 jmethodID toLongMethod = (*env)->GetMethodID(env, platformAddrClass,
2356 checkResult = (void*)(u4)(*env)->CallLongMethod(env, platformAddr,
2360 if (platformAddr != NULL)
2361 (*env)->DeleteLocalRef(env, platformAddr);
2363 if (result != checkResult) {
2364 LOGW("JNI WARNING: direct buffer result mismatch (%p vs %p)\n",
2365 result, checkResult);
2374 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
2376 CHECK_ENTER(env, kFlag_Default);
2377 CHECK_OBJECT(env, buf);
2378 /* TODO: verify "buf" is an instance of java.nio.Buffer */
2379 jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2386 * ===========================================================================
2387 * JNI invocation functions
2388 * ===========================================================================
2391 static jint Check_DestroyJavaVM(JavaVM* vm)
2393 CHECK_VMENTER(vm, false);
2395 result = BASE_VM(vm)->DestroyJavaVM(vm);
2396 CHECK_VMEXIT(vm, false);
2400 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2403 CHECK_VMENTER(vm, false);
2405 result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2406 CHECK_VMEXIT(vm, true);
2410 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2413 CHECK_VMENTER(vm, false);
2415 result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2416 CHECK_VMEXIT(vm, true);
2420 static jint Check_DetachCurrentThread(JavaVM* vm)
2422 CHECK_VMENTER(vm, true);
2424 result = BASE_VM(vm)->DetachCurrentThread(vm);
2425 CHECK_VMEXIT(vm, false);
2429 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2431 CHECK_VMENTER(vm, true);
2433 result = BASE_VM(vm)->GetEnv(vm, env, version);
2434 CHECK_VMEXIT(vm, true);
2440 * ===========================================================================
2442 * ===========================================================================
2445 static const struct JNINativeInterface gCheckNativeInterface = {
2456 Check_FromReflectedMethod,
2457 Check_FromReflectedField,
2458 Check_ToReflectedMethod,
2460 Check_GetSuperclass,
2461 Check_IsAssignableFrom,
2463 Check_ToReflectedField,
2467 Check_ExceptionOccurred,
2468 Check_ExceptionDescribe,
2469 Check_ExceptionClear,
2472 Check_PushLocalFrame,
2473 Check_PopLocalFrame,
2476 Check_DeleteGlobalRef,
2477 Check_DeleteLocalRef,
2480 Check_EnsureLocalCapacity,
2487 Check_GetObjectClass,
2492 Check_CallObjectMethod,
2493 Check_CallObjectMethodV,
2494 Check_CallObjectMethodA,
2495 Check_CallBooleanMethod,
2496 Check_CallBooleanMethodV,
2497 Check_CallBooleanMethodA,
2498 Check_CallByteMethod,
2499 Check_CallByteMethodV,
2500 Check_CallByteMethodA,
2501 Check_CallCharMethod,
2502 Check_CallCharMethodV,
2503 Check_CallCharMethodA,
2504 Check_CallShortMethod,
2505 Check_CallShortMethodV,
2506 Check_CallShortMethodA,
2507 Check_CallIntMethod,
2508 Check_CallIntMethodV,
2509 Check_CallIntMethodA,
2510 Check_CallLongMethod,
2511 Check_CallLongMethodV,
2512 Check_CallLongMethodA,
2513 Check_CallFloatMethod,
2514 Check_CallFloatMethodV,
2515 Check_CallFloatMethodA,
2516 Check_CallDoubleMethod,
2517 Check_CallDoubleMethodV,
2518 Check_CallDoubleMethodA,
2519 Check_CallVoidMethod,
2520 Check_CallVoidMethodV,
2521 Check_CallVoidMethodA,
2523 Check_CallNonvirtualObjectMethod,
2524 Check_CallNonvirtualObjectMethodV,
2525 Check_CallNonvirtualObjectMethodA,
2526 Check_CallNonvirtualBooleanMethod,
2527 Check_CallNonvirtualBooleanMethodV,
2528 Check_CallNonvirtualBooleanMethodA,
2529 Check_CallNonvirtualByteMethod,
2530 Check_CallNonvirtualByteMethodV,
2531 Check_CallNonvirtualByteMethodA,
2532 Check_CallNonvirtualCharMethod,
2533 Check_CallNonvirtualCharMethodV,
2534 Check_CallNonvirtualCharMethodA,
2535 Check_CallNonvirtualShortMethod,
2536 Check_CallNonvirtualShortMethodV,
2537 Check_CallNonvirtualShortMethodA,
2538 Check_CallNonvirtualIntMethod,
2539 Check_CallNonvirtualIntMethodV,
2540 Check_CallNonvirtualIntMethodA,
2541 Check_CallNonvirtualLongMethod,
2542 Check_CallNonvirtualLongMethodV,
2543 Check_CallNonvirtualLongMethodA,
2544 Check_CallNonvirtualFloatMethod,
2545 Check_CallNonvirtualFloatMethodV,
2546 Check_CallNonvirtualFloatMethodA,
2547 Check_CallNonvirtualDoubleMethod,
2548 Check_CallNonvirtualDoubleMethodV,
2549 Check_CallNonvirtualDoubleMethodA,
2550 Check_CallNonvirtualVoidMethod,
2551 Check_CallNonvirtualVoidMethodV,
2552 Check_CallNonvirtualVoidMethodA,
2556 Check_GetObjectField,
2557 Check_GetBooleanField,
2560 Check_GetShortField,
2563 Check_GetFloatField,
2564 Check_GetDoubleField,
2565 Check_SetObjectField,
2566 Check_SetBooleanField,
2569 Check_SetShortField,
2572 Check_SetFloatField,
2573 Check_SetDoubleField,
2575 Check_GetStaticMethodID,
2577 Check_CallStaticObjectMethod,
2578 Check_CallStaticObjectMethodV,
2579 Check_CallStaticObjectMethodA,
2580 Check_CallStaticBooleanMethod,
2581 Check_CallStaticBooleanMethodV,
2582 Check_CallStaticBooleanMethodA,
2583 Check_CallStaticByteMethod,
2584 Check_CallStaticByteMethodV,
2585 Check_CallStaticByteMethodA,
2586 Check_CallStaticCharMethod,
2587 Check_CallStaticCharMethodV,
2588 Check_CallStaticCharMethodA,
2589 Check_CallStaticShortMethod,
2590 Check_CallStaticShortMethodV,
2591 Check_CallStaticShortMethodA,
2592 Check_CallStaticIntMethod,
2593 Check_CallStaticIntMethodV,
2594 Check_CallStaticIntMethodA,
2595 Check_CallStaticLongMethod,
2596 Check_CallStaticLongMethodV,
2597 Check_CallStaticLongMethodA,
2598 Check_CallStaticFloatMethod,
2599 Check_CallStaticFloatMethodV,
2600 Check_CallStaticFloatMethodA,
2601 Check_CallStaticDoubleMethod,
2602 Check_CallStaticDoubleMethodV,
2603 Check_CallStaticDoubleMethodA,
2604 Check_CallStaticVoidMethod,
2605 Check_CallStaticVoidMethodV,
2606 Check_CallStaticVoidMethodA,
2608 Check_GetStaticFieldID,
2610 Check_GetStaticObjectField,
2611 Check_GetStaticBooleanField,
2612 Check_GetStaticByteField,
2613 Check_GetStaticCharField,
2614 Check_GetStaticShortField,
2615 Check_GetStaticIntField,
2616 Check_GetStaticLongField,
2617 Check_GetStaticFloatField,
2618 Check_GetStaticDoubleField,
2620 Check_SetStaticObjectField,
2621 Check_SetStaticBooleanField,
2622 Check_SetStaticByteField,
2623 Check_SetStaticCharField,
2624 Check_SetStaticShortField,
2625 Check_SetStaticIntField,
2626 Check_SetStaticLongField,
2627 Check_SetStaticFloatField,
2628 Check_SetStaticDoubleField,
2632 Check_GetStringLength,
2633 Check_GetStringChars,
2634 Check_ReleaseStringChars,
2637 Check_GetStringUTFLength,
2638 Check_GetStringUTFChars,
2639 Check_ReleaseStringUTFChars,
2641 Check_GetArrayLength,
2642 Check_NewObjectArray,
2643 Check_GetObjectArrayElement,
2644 Check_SetObjectArrayElement,
2646 Check_NewBooleanArray,
2649 Check_NewShortArray,
2652 Check_NewFloatArray,
2653 Check_NewDoubleArray,
2655 Check_GetBooleanArrayElements,
2656 Check_GetByteArrayElements,
2657 Check_GetCharArrayElements,
2658 Check_GetShortArrayElements,
2659 Check_GetIntArrayElements,
2660 Check_GetLongArrayElements,
2661 Check_GetFloatArrayElements,
2662 Check_GetDoubleArrayElements,
2664 Check_ReleaseBooleanArrayElements,
2665 Check_ReleaseByteArrayElements,
2666 Check_ReleaseCharArrayElements,
2667 Check_ReleaseShortArrayElements,
2668 Check_ReleaseIntArrayElements,
2669 Check_ReleaseLongArrayElements,
2670 Check_ReleaseFloatArrayElements,
2671 Check_ReleaseDoubleArrayElements,
2673 Check_GetBooleanArrayRegion,
2674 Check_GetByteArrayRegion,
2675 Check_GetCharArrayRegion,
2676 Check_GetShortArrayRegion,
2677 Check_GetIntArrayRegion,
2678 Check_GetLongArrayRegion,
2679 Check_GetFloatArrayRegion,
2680 Check_GetDoubleArrayRegion,
2681 Check_SetBooleanArrayRegion,
2682 Check_SetByteArrayRegion,
2683 Check_SetCharArrayRegion,
2684 Check_SetShortArrayRegion,
2685 Check_SetIntArrayRegion,
2686 Check_SetLongArrayRegion,
2687 Check_SetFloatArrayRegion,
2688 Check_SetDoubleArrayRegion,
2690 Check_RegisterNatives,
2691 Check_UnregisterNatives,
2698 Check_GetStringRegion,
2699 Check_GetStringUTFRegion,
2701 Check_GetPrimitiveArrayCritical,
2702 Check_ReleasePrimitiveArrayCritical,
2704 Check_GetStringCritical,
2705 Check_ReleaseStringCritical,
2707 Check_NewWeakGlobalRef,
2708 Check_DeleteWeakGlobalRef,
2710 Check_ExceptionCheck,
2712 Check_NewDirectByteBuffer,
2713 Check_GetDirectBufferAddress,
2714 Check_GetDirectBufferCapacity,
2716 Check_GetObjectRefType
2718 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2723 Check_DestroyJavaVM,
2724 Check_AttachCurrentThread,
2725 Check_DetachCurrentThread,
2729 Check_AttachCurrentThreadAsDaemon,
2734 * Replace the normal table with the checked table.
2736 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2738 assert(pEnv->funcTable != &gCheckNativeInterface);
2739 pEnv->baseFuncTable = pEnv->funcTable;
2740 pEnv->funcTable = &gCheckNativeInterface;
2744 * Replace the normal table with the checked table.
2746 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2748 assert(pVm->funcTable != &gCheckInvokeInterface);
2749 pVm->baseFuncTable = pVm->funcTable;
2750 pVm->funcTable = &gCheckInvokeInterface;