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)",
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'",
98 LOGW(" failed in %s.%s ('%s' not found)",
99 method->clazz->descriptor, method->name, declType);
103 if (!dvmInstanceof(objClazz, declClazz)) {
104 LOGW("JNI WARNING: method declared to return '%s' returned '%s'",
106 LOGW(" failed in %s.%s",
107 method->clazz->descriptor, method->name);
111 LOGV("Check %s.%s: %s io %s (SLOW-OK)",
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)
188 * Flags passed into checkThread().
190 #define kFlag_Default 0x0000
192 #define kFlag_CritBad 0x0000 /* calling while in critical is bad */
193 #define kFlag_CritOkay 0x0001 /* ...okay */
194 #define kFlag_CritGet 0x0002 /* this is a critical "get" */
195 #define kFlag_CritRelease 0x0003 /* this is a critical "release" */
196 #define kFlag_CritMask 0x0003 /* bit mask to get "crit" value */
198 #define kFlag_ExcepBad 0x0000 /* raised exceptions are bad */
199 #define kFlag_ExcepOkay 0x0004 /* ...okay */
202 * Enter/exit macros for JNI env "check" functions. These do not change
203 * the thread state within the VM.
205 #define CHECK_ENTER(_env, _flags) \
207 JNI_TRACE(true, true); \
208 checkThread(_env, _flags, __FUNCTION__); \
211 #define CHECK_EXIT(_env) \
212 do { JNI_TRACE(false, true); } while(false)
216 * Enter/exit macros for JNI invocation interface "check" functions. These
217 * do not change the thread state within the VM.
219 * Set "_hasmeth" to true if we have a valid thread with a method pointer.
220 * We won't have one before attaching a thread, after detaching a thread, or
221 * after destroying the VM.
223 #define CHECK_VMENTER(_vm, _hasmeth) \
224 do { JNI_TRACE(true, _hasmeth); } while(false)
225 #define CHECK_VMEXIT(_vm, _hasmeth) \
226 do { JNI_TRACE(false, _hasmeth); } while(false)
228 #define CHECK_FIELD_TYPE(_env, _obj, _fieldid, _prim, _isstatic) \
229 checkFieldType(_env, _obj, _fieldid, _prim, _isstatic, __FUNCTION__)
230 #define CHECK_INST_FIELD_ID(_env, _obj, _fieldid) \
231 checkInstanceFieldID(_env, _obj, _fieldid, __FUNCTION__)
232 #define CHECK_CLASS(_env, _clazz) \
233 checkClass(_env, _clazz, __FUNCTION__)
234 #define CHECK_STRING(_env, _str) \
235 checkString(_env, _str, __FUNCTION__)
236 #define CHECK_UTF_STRING(_env, _str) \
237 checkUtfString(_env, _str, #_str, __FUNCTION__)
238 #define CHECK_NULLABLE_UTF_STRING(_env, _str) \
239 checkUtfString(_env, _str, NULL, __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_VIRTUAL_METHOD(_env, _obj, _methid) \
255 checkVirtualMethod(_env, _obj, _methid, __FUNCTION__)
256 #define CHECK_STATIC_METHOD(_env, _clazz, _methid) \
257 checkStaticMethod(_env, _clazz, _methid, __FUNCTION__)
258 #define CHECK_METHOD_ARGS_A(_env, _methid, _args) \
259 checkMethodArgsA(_env, _methid, _args, __FUNCTION__)
260 #define CHECK_METHOD_ARGS_V(_env, _methid, _args) \
261 checkMethodArgsV(_env, _methid, _args, __FUNCTION__)
264 * Prints trace messages when a native method calls a JNI function such as
265 * NewByteArray. Enabled if both "-Xcheck:jni" and "-verbose:jni" are enabled.
267 #define JNI_TRACE(_entry, _hasmeth) \
269 if (gDvm.verboseJni && (_entry)) { \
270 static const char* classDescriptor = "???"; \
271 static const char* methodName = "???"; \
273 const Method* meth = dvmGetCurrentJNIMethod(); \
274 classDescriptor = meth->clazz->descriptor; \
275 methodName = meth->name; \
277 /* use +6 to drop the leading "Check_" */ \
278 LOGI("JNI: %s (from %s.%s)", \
279 (__FUNCTION__)+6, classDescriptor, methodName); \
284 * Log the current location.
286 * "func" looks like "Check_DeleteLocalRef"; we drop the "Check_".
288 static void showLocation(const Method* meth, const char* func)
290 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
291 LOGW(" in %s.%s %s (%s)",
292 meth->clazz->descriptor, meth->name, desc, func + 6);
297 * Abort if we are configured to bail out on JNI warnings.
299 static void abortMaybe(void)
301 JavaVMExt* vm = (JavaVMExt*) gDvm.vmList;
303 dvmDumpThread(dvmThreadSelf(), false);
309 * Verify that the current thread is (a) attached and (b) associated with
310 * this particular instance of JNIEnv.
312 * Verify that, if this thread previously made a critical "get" call, we
313 * do the corresponding "release" call before we try anything else.
315 * Verify that, if an exception has been raised, the native code doesn't
316 * make any JNI calls other than the Exception* methods.
318 * TODO? if we add support for non-JNI native calls, make sure that the
319 * method at the top of the interpreted stack is a JNI method call. (Or
320 * set a flag in the Thread/JNIEnv when the call is made and clear it on
323 * NOTE: we are still in THREAD_NATIVE mode. A GC could happen at any time.
325 static void checkThread(JNIEnv* env, int flags, const char* func)
327 JNIEnvExt* threadEnv;
328 bool printWarn = false;
329 bool printException = false;
331 /* get the *correct* JNIEnv by going through our TLS pointer */
332 threadEnv = dvmGetJNIEnvForThread();
335 * Verify that the JNIEnv we've been handed matches what we expected
338 if (threadEnv == NULL) {
339 LOGE("JNI ERROR: non-VM thread making JNI calls");
340 // don't set printWarn -- it'll try to call showLocation()
342 } else if ((JNIEnvExt*) env != threadEnv) {
343 if (dvmThreadSelf()->threadId != threadEnv->envThreadId) {
344 LOGE("JNI: threadEnv != thread->env?");
348 LOGW("JNI WARNING: threadid=%d using env from threadid=%d",
349 threadEnv->envThreadId, ((JNIEnvExt*)env)->envThreadId);
352 /* this is a bad idea -- need to throw as we exit, or abort func */
353 //dvmThrowException("Ljava/lang/RuntimeException;",
354 // "invalid use of JNI env ptr");
355 } else if (((JNIEnvExt*) env)->self != dvmThreadSelf()) {
356 /* correct JNIEnv*; make sure the "self" pointer is correct */
357 LOGE("JNI ERROR: env->self != thread-self (%p vs. %p)",
358 ((JNIEnvExt*) env)->self, dvmThreadSelf());
363 * Check for critical resource misuse.
365 switch (flags & kFlag_CritMask) {
366 case kFlag_CritOkay: // okay to call this method
368 case kFlag_CritBad: // not okay to call
369 if (threadEnv->critical) {
370 LOGW("JNI WARNING: threadid=%d using JNI after critical get",
371 threadEnv->envThreadId);
375 case kFlag_CritGet: // this is a "get" call
376 /* don't check here; we allow nested gets */
377 threadEnv->critical++;
379 case kFlag_CritRelease: // this is a "release" call
380 threadEnv->critical--;
381 if (threadEnv->critical < 0) {
382 LOGW("JNI WARNING: threadid=%d called too many crit releases",
383 threadEnv->envThreadId);
392 * Check for raised exceptions.
394 if ((flags & kFlag_ExcepOkay) == 0 && dvmCheckException(dvmThreadSelf())) {
395 LOGW("JNI WARNING: JNI method called with exception raised");
397 printException = true;
401 showLocation(dvmGetCurrentJNIMethod(), func);
402 if (printException) {
403 LOGW("Pending exception is:");
404 dvmLogExceptionStackTrace();
411 * Verify that the field is of the appropriate type. If the field has an
412 * object type, "obj" is the object we're trying to assign into it.
414 * Works for both static and instance fields.
416 static void checkFieldType(JNIEnv* env, jobject jobj, jfieldID fieldID,
417 PrimitiveType prim, bool isStatic, const char* func)
419 static const char* primNameList[] = {
420 "Object/Array", "boolean", "char", "float", "double",
421 "byte", "short", "int", "long", "void"
423 const char** primNames = &primNameList[1]; // shift up for PRIM_NOT
424 Field* field = (Field*) fieldID;
425 bool printWarn = false;
427 if (fieldID == NULL) {
428 LOGE("JNI ERROR: null field ID");
432 if (field->signature[0] == 'L' || field->signature[0] == '[') {
433 Object* obj = dvmDecodeIndirectRef(env, jobj);
435 ClassObject* fieldClass =
436 dvmFindLoadedClass(field->signature);
437 ClassObject* objClass = obj->clazz;
439 assert(fieldClass != NULL);
440 assert(objClass != NULL);
442 if (!dvmInstanceof(objClass, fieldClass)) {
443 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)",
444 field->name, field->signature, objClass->descriptor);
448 } else if (field->signature[0] != PRIM_TYPE_TO_LETTER[prim]) {
449 LOGW("JNI WARNING: field '%s' with type '%s' set with wrong type (%s)",
450 field->name, field->signature, primNames[prim]);
452 } else if (isStatic && !dvmIsStaticField(field)) {
454 LOGW("JNI WARNING: accessing non-static field %s as static",
457 LOGW("JNI WARNING: accessing static field %s as non-static",
463 showLocation(dvmGetCurrentJNIMethod(), func);
469 * Verify that "jobj" is a valid object, and that it's an object that JNI
470 * is allowed to know about. We allow NULL references.
472 * Must be in "running" mode before calling here.
474 static void checkObject0(JNIEnv* env, jobject jobj, const char* func)
476 UNUSED_PARAMETER(env);
477 bool printWarn = false;
482 if (dvmIsWeakGlobalRef(jobj)) {
484 * Normalize and continue. This will tell us if the PhantomReference
487 jobj = dvmNormalizeWeakGlobalRef((jweak) jobj);
490 if (dvmGetJNIRefType(env, jobj) == JNIInvalidRefType) {
491 LOGW("JNI WARNING: %p is not a valid JNI reference", jobj);
494 Object* obj = dvmDecodeIndirectRef(env, jobj);
496 if (obj == NULL || !dvmIsValidObject(obj)) {
497 LOGW("JNI WARNING: native code passing in bad object %p %p (%s)",
504 showLocation(dvmGetCurrentJNIMethod(), func);
510 * Verify that "jobj" is a valid object, and that it's an object that JNI
511 * is allowed to know about. We allow NULL references.
513 * Switches to "running" mode before performing checks.
515 static void checkObject(JNIEnv* env, jobject jobj, const char* func)
518 checkObject0(env, jobj, func);
523 * Verify that "clazz" actually points to a class object. (Also performs
526 * We probably don't need to identify where we're being called from,
527 * because the VM is most likely about to crash and leave a core dump
528 * if something is wrong.
530 * Because we're looking at an object on the GC heap, we have to switch
531 * to "running" mode before doing the checks.
533 static void checkClass(JNIEnv* env, jclass jclazz, const char* func)
536 bool printWarn = false;
538 Object* obj = dvmDecodeIndirectRef(env, jclazz);
541 LOGW("JNI WARNING: received null jclass");
543 } else if (!dvmIsValidObject(obj)) {
544 LOGW("JNI WARNING: jclass points to invalid object %p", obj);
546 } else if (obj->clazz != gDvm.classJavaLangClass) {
547 LOGW("JNI WARNING: jclass arg is not a Class reference "
548 "(%p is instance of %s)",
549 jclazz, obj->clazz->descriptor);
557 checkObject(env, jclazz, func);
561 * Verify that "str" is non-NULL and points to a String object.
563 * Since we're dealing with objects, switch to "running" mode.
565 static void checkString(JNIEnv* env, jstring jstr, const char* func)
568 bool printWarn = false;
570 Object* obj = dvmDecodeIndirectRef(env, jstr);
573 LOGW("JNI WARNING: received null jstring (%s)", func);
575 } else if (obj->clazz != gDvm.classJavaLangString) {
577 * TODO: we probably should test dvmIsValidObject first, because
578 * this will crash if "obj" is non-null but pointing to an invalid
579 * memory region. However, the "is valid" test is a little slow,
580 * we're doing it again over in checkObject().
582 if (dvmIsValidObject(obj))
583 LOGW("JNI WARNING: jstring %p points to non-string object (%s)",
586 LOGW("JNI WARNING: jstring %p is not a valid object (%s)", jstr,
595 checkObject(env, jstr, func);
599 * Verify that "bytes" points to valid "modified UTF-8" data.
600 * If "identifier" is NULL, "bytes" is allowed to be NULL; otherwise,
601 * "identifier" is the name to use when reporting the null pointer.
603 static void checkUtfString(JNIEnv* env, const char* bytes,
604 const char* identifier, const char* func)
606 const char* origBytes = bytes;
609 if (identifier != NULL) {
610 LOGW("JNI WARNING: %s == NULL", identifier);
617 const char* errorKind = NULL;
619 while (*bytes != '\0') {
621 // Switch on the high four bits.
631 // Bit pattern 0xxx. No need for any extra bytes.
640 * Bit pattern 10xx or 1111, which are illegal start bytes.
641 * Note: 1111 is valid for normal UTF-8, but not the
642 * modified UTF-8 used here.
645 goto fail_with_string;
648 // Bit pattern 1110, so there are two additional bytes.
650 if ((utf8 & 0xc0) != 0x80) {
651 errorKind = "continuation";
652 goto fail_with_string;
654 // Fall through to take care of the final byte.
658 // Bit pattern 110x, so there is one additional byte.
660 if ((utf8 & 0xc0) != 0x80) {
661 errorKind = "continuation";
662 goto fail_with_string;
672 LOGW("JNI WARNING: input is not valid UTF-8: illegal %s byte 0x%x",
674 LOGW(" string: '%s'", origBytes);
676 showLocation(dvmGetCurrentJNIMethod(), func);
681 * In some circumstances the VM will screen class names, but it doesn't
682 * for class lookup. When things get bounced through a class loader, they
683 * can actually get normalized a couple of times; as a result, passing in
684 * a class name like "java.lang.Thread" instead of "java/lang/Thread" will
685 * work in some circumstances.
687 * This is incorrect and could cause strange behavior or compatibility
688 * problems, so we want to screen that out here.
690 * We expect "full-qualified" class names, like "java/lang/Thread" or
691 * "[Ljava/lang/Object;".
693 static void checkClassName(JNIEnv* env, const char* className, const char* func)
697 /* quick check for illegal chars */
699 while (*cp != '\0') {
700 if (*cp == '.') /* catch "java.lang.String" */
704 if (*(cp-1) == ';' && *className == 'L')
705 goto fail; /* catch "Ljava/lang/String;" */
707 // TODO: need a more rigorous check here
712 LOGW("JNI WARNING: illegal class name '%s' (%s)", className, func);
713 LOGW(" (should be formed like 'java/lang/String')");
718 * Verify that "array" is non-NULL and points to an Array object.
720 * Since we're dealing with objects, switch to "running" mode.
722 static void checkArray(JNIEnv* env, jarray jarr, const char* func)
725 bool printWarn = false;
727 Object* obj = dvmDecodeIndirectRef(env, jarr);
730 LOGW("JNI WARNING: received null array (%s)", func);
732 } else if (obj->clazz->descriptor[0] != '[') {
733 if (dvmIsValidObject(obj))
734 LOGW("JNI WARNING: jarray %p points to non-array object (%s)",
735 jarr, obj->clazz->descriptor);
737 LOGW("JNI WARNING: jarray %p is not a valid object", jarr);
746 checkObject(env, jarr, func);
750 * Verify that the "mode" argument passed to a primitive array Release
751 * function is one of the valid values.
753 static void checkReleaseMode(JNIEnv* env, jint mode, const char* func)
755 if (mode != 0 && mode != JNI_COMMIT && mode != JNI_ABORT) {
756 LOGW("JNI WARNING: bad value for mode (%d) (%s)", mode, func);
762 * Verify that the length argument to array-creation calls is >= 0.
764 static void checkLengthPositive(JNIEnv* env, jsize length, const char* func)
767 LOGW("JNI WARNING: negative length for array allocation (%s)", func);
773 * Verify that the pointer value is non-NULL.
775 static void checkNonNull(JNIEnv* env, const void* ptr, const char* func)
778 LOGW("JNI WARNING: invalid null pointer (%s)", func);
784 * Verify that the method's return type matches the type of call.
786 * "expectedSigByte" will be 'L' for all objects, including arrays.
788 static void checkSig(JNIEnv* env, jmethodID methodID, char expectedSigByte,
789 bool isStatic, const char* func)
791 const Method* meth = (const Method*) methodID;
792 bool printWarn = false;
794 if (expectedSigByte != meth->shorty[0]) {
795 LOGW("JNI WARNING: expected return type '%c'", expectedSigByte);
797 } else if (isStatic && !dvmIsStaticMethod(meth)) {
799 LOGW("JNI WARNING: calling non-static method with static call");
801 LOGW("JNI WARNING: calling static method with non-static call");
806 char* desc = dexProtoCopyMethodDescriptor(&meth->prototype);
807 LOGW(" calling %s.%s %s",
808 meth->clazz->descriptor, meth->name, desc);
810 showLocation(dvmGetCurrentJNIMethod(), func);
816 * Verify that this static field ID is valid for this class.
818 static void checkStaticFieldID(JNIEnv* env, jclass jclazz, jfieldID fieldID)
820 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
821 StaticField* base = &clazz->sfields[0];
822 int fieldCount = clazz->sfieldCount;
824 if ((StaticField*) fieldID < base ||
825 (StaticField*) fieldID >= base + fieldCount)
827 LOGW("JNI WARNING: static fieldID %p not valid for class %s",
828 fieldID, clazz->descriptor);
829 LOGW(" base=%p count=%d", base, fieldCount);
835 * Verify that this instance field ID is valid for this object.
837 static void checkInstanceFieldID(JNIEnv* env, jobject jobj, jfieldID fieldID,
843 LOGW("JNI WARNING: invalid null object (%s)", func);
848 Object* obj = dvmDecodeIndirectRef(env, jobj);
849 ClassObject* clazz = obj->clazz;
852 * Check this class and all of its superclasses for a matching field.
853 * Don't need to scan interfaces.
855 while (clazz != NULL) {
856 if ((InstField*) fieldID >= clazz->ifields &&
857 (InstField*) fieldID < clazz->ifields + clazz->ifieldCount)
862 clazz = clazz->super;
865 LOGW("JNI WARNING: inst fieldID %p not valid for class %s",
866 fieldID, obj->clazz->descriptor);
874 * Verify that "methodID" is appropriate for "jobj".
876 * Make sure the object is an instance of the method's declaring class.
877 * (Note the methodID might point to a declaration in an interface; this
878 * will be handled automatically by the instanceof check.)
880 static void checkVirtualMethod(JNIEnv* env, jobject jobj, jmethodID methodID,
885 Object* obj = dvmDecodeIndirectRef(env, jobj);
886 const Method* meth = (const Method*) methodID;
888 if (!dvmInstanceof(obj->clazz, meth->clazz)) {
889 LOGW("JNI WARNING: can't call %s.%s on instance of %s",
890 meth->clazz->descriptor, meth->name, obj->clazz->descriptor);
898 * Verify that "methodID" is appropriate for "clazz".
900 * A mismatch isn't dangerous, because the method defines the class. In
901 * fact, jclazz is unused in the implementation. It's best if we don't
902 * allow bad code in the system though.
904 * Instances of "jclazz" must be instances of the method's declaring class.
906 static void checkStaticMethod(JNIEnv* env, jclass jclazz, jmethodID methodID,
911 ClassObject* clazz = (ClassObject*) dvmDecodeIndirectRef(env, jclazz);
912 const Method* meth = (const Method*) methodID;
914 if (!dvmInstanceof(clazz, meth->clazz)) {
915 LOGW("JNI WARNING: can't call static %s.%s on class %s",
916 meth->clazz->descriptor, meth->name, clazz->descriptor);
924 * Verify that the reference arguments being passed in are appropriate for
927 * At a minimum we want to make sure that the argument is a valid
928 * reference. We can also do a class lookup on the method signature
929 * and verify that the object is an instance of the appropriate class,
930 * but that's more expensive.
932 * The basic tests are redundant when indirect references are enabled,
933 * since reference arguments must always be converted explicitly. An
934 * instanceof test would not be redundant, but we're not doing that at
937 static void checkMethodArgsV(JNIEnv* env, jmethodID methodID, va_list args,
940 #ifndef USE_INDIRECT_REF
943 const Method* meth = (const Method*) methodID;
944 const char* desc = meth->shorty;
946 LOGV("V-checking %s.%s:%s...", meth->clazz->descriptor, meth->name, desc);
948 while (*++desc != '\0') { /* pre-incr to skip return type */
951 { /* 'shorty' descr uses L for all refs, incl array */
952 jobject argObj = va_arg(args, jobject);
953 checkObject0(env, argObj, func);
956 case 'D': /* 8-byte double */
957 case 'J': /* 8-byte long */
958 case 'F': /* floats normalized to doubles */
959 (void) va_arg(args, u8);
961 default: /* Z B C S I -- all passed as 32-bit integers */
962 (void) va_arg(args, u4);
972 * Same purpose as checkMethodArgsV, but with arguments in an array of
975 static void checkMethodArgsA(JNIEnv* env, jmethodID methodID, jvalue* args,
978 #ifndef USE_INDIRECT_REF
981 const Method* meth = (const Method*) methodID;
982 const char* desc = meth->shorty;
985 LOGV("A-checking %s.%s:%s...", meth->clazz->descriptor, meth->name, desc);
987 while (*++desc != '\0') { /* pre-incr to skip return type */
989 jobject argObj = args[idx].l;
990 checkObject0(env, argObj, func);
1002 * ===========================================================================
1004 * ===========================================================================
1007 #define kGuardLen 512 /* must be multiple of 2 */
1008 #define kGuardPattern 0xd5e3 /* uncommon values; d5e3d5e3 invalid addr */
1009 #define kGuardMagic 0xffd5aa96
1010 #define kGuardExtra sizeof(GuardExtra)
1012 /* this gets tucked in at the start of the buffer; struct size must be even */
1013 typedef struct GuardExtra {
1017 const void* originalPtr;
1020 /* find the GuardExtra given the pointer into the "live" data */
1021 inline static GuardExtra* getGuardExtra(const void* dataBuf)
1023 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
1024 return (GuardExtra*) fullBuf;
1028 * Create an oversized buffer to hold the contents of "buf". Copy it in,
1029 * filling in the area around it with guard data.
1031 * We use a 16-bit pattern to make a rogue memset less likely to elude us.
1033 static void* createGuardedCopy(const void* buf, size_t len, bool modOkay)
1036 size_t newLen = (len + kGuardLen +1) & ~0x01;
1041 newBuf = (u1*)malloc(newLen);
1042 if (newBuf == NULL) {
1043 LOGE("createGuardedCopy failed on alloc of %d bytes", newLen);
1047 /* fill it in with a pattern */
1049 for (i = 0; i < (int)newLen / 2; i++)
1050 *pat++ = kGuardPattern;
1052 /* copy the data in; note "len" could be zero */
1053 memcpy(newBuf + kGuardLen / 2, buf, len);
1055 /* if modification is not expected, grab a checksum */
1058 adler = adler32(0L, Z_NULL, 0);
1059 adler = adler32(adler, buf, len);
1060 *(uLong*)newBuf = adler;
1063 pExtra = (GuardExtra*) newBuf;
1064 pExtra->magic = kGuardMagic;
1065 pExtra->adler = adler;
1066 pExtra->originalPtr = buf;
1067 pExtra->originalLen = len;
1069 return newBuf + kGuardLen / 2;
1073 * Verify the guard area and, if "modOkay" is false, that the data itself
1074 * has not been altered.
1076 * The caller has already checked that "dataBuf" is non-NULL.
1078 static bool checkGuardedCopy(const void* dataBuf, bool modOkay)
1080 static const u4 kMagicCmp = kGuardMagic;
1081 const u1* fullBuf = ((const u1*) dataBuf) - kGuardLen / 2;
1082 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1088 * Before we do anything with "pExtra", check the magic number. We
1089 * do the check with memcmp rather than "==" in case the pointer is
1090 * unaligned. If it points to completely bogus memory we're going
1091 * to crash, but there's no easy way around that.
1093 if (memcmp(&pExtra->magic, &kMagicCmp, 4) != 0) {
1095 memcpy(buf, &pExtra->magic, 4);
1096 LOGE("JNI: guard magic does not match (found 0x%02x%02x%02x%02x) "
1097 "-- incorrect data pointer %p?",
1098 buf[3], buf[2], buf[1], buf[0], dataBuf); /* assume little endian */
1102 len = pExtra->originalLen;
1104 /* check bottom half of guard; skip over optional checksum storage */
1105 pat = (u2*) fullBuf;
1106 for (i = kGuardExtra / 2; i < (int) (kGuardLen / 2 - kGuardExtra) / 2; i++)
1108 if (pat[i] != kGuardPattern) {
1109 LOGE("JNI: guard pattern(1) disturbed at %p + %d",
1115 int offset = kGuardLen / 2 + len;
1116 if (offset & 0x01) {
1117 /* odd byte; expected value depends on endian-ness of host */
1118 const u2 patSample = kGuardPattern;
1119 if (fullBuf[offset] != ((const u1*) &patSample)[1]) {
1120 LOGE("JNI: guard pattern disturbed in odd byte after %p "
1121 "(+%d) 0x%02x 0x%02x",
1122 fullBuf, offset, fullBuf[offset], ((const u1*) &patSample)[1]);
1128 /* check top half of guard */
1129 pat = (u2*) (fullBuf + offset);
1130 for (i = 0; i < kGuardLen / 4; i++) {
1131 if (pat[i] != kGuardPattern) {
1132 LOGE("JNI: guard pattern(2) disturbed at %p + %d",
1133 fullBuf, offset + i*2);
1139 * If modification is not expected, verify checksum. Strictly speaking
1140 * this is wrong: if we told the client that we made a copy, there's no
1141 * reason they can't alter the buffer.
1144 uLong adler = adler32(0L, Z_NULL, 0);
1145 adler = adler32(adler, dataBuf, len);
1146 if (pExtra->adler != adler) {
1147 LOGE("JNI: buffer modified (0x%08lx vs 0x%08lx) at addr %p",
1148 pExtra->adler, adler, dataBuf);
1157 * Free up the guard buffer, scrub it, and return the original pointer.
1159 static void* freeGuardedCopy(void* dataBuf)
1161 u1* fullBuf = ((u1*) dataBuf) - kGuardLen / 2;
1162 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1163 void* originalPtr = (void*) pExtra->originalPtr;
1164 size_t len = pExtra->originalLen;
1166 memset(dataBuf, 0xdd, len);
1172 * Just pull out the original pointer.
1174 static void* getGuardedCopyOriginalPtr(const void* dataBuf)
1176 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1177 return (void*) pExtra->originalPtr;
1181 * Grab the data length.
1183 static size_t getGuardedCopyOriginalLen(const void* dataBuf)
1185 const GuardExtra* pExtra = getGuardExtra(dataBuf);
1186 return pExtra->originalLen;
1190 * Return the width, in bytes, of a primitive type.
1192 static int dvmPrimitiveTypeWidth(PrimitiveType primType)
1194 static const int lengths[PRIM_MAX] = {
1205 assert(primType >= 0 && primType < PRIM_MAX);
1206 return lengths[primType];
1210 * Create a guarded copy of a primitive array. Modifications to the copied
1211 * data are allowed. Returns a pointer to the copied data.
1213 static void* createGuardedPACopy(JNIEnv* env, const jarray jarr,
1216 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1217 PrimitiveType primType = arrObj->obj.clazz->elementClass->primitiveType;
1218 int len = arrObj->length * dvmPrimitiveTypeWidth(primType);
1221 result = createGuardedCopy(arrObj->contents, len, true);
1230 * Perform the array "release" operation, which may or may not copy data
1231 * back into the VM, and may or may not release the underlying storage.
1233 static void* releaseGuardedPACopy(JNIEnv* env, jarray jarr, void* dataBuf,
1236 ArrayObject* arrObj = (ArrayObject*) dvmDecodeIndirectRef(env, jarr);
1237 bool release, copyBack;
1240 if (!checkGuardedCopy(dataBuf, true)) {
1241 LOGE("JNI: failed guarded copy check in releaseGuardedPACopy");
1248 release = copyBack = true;
1259 LOGE("JNI: bad release mode %d", mode);
1265 size_t len = getGuardedCopyOriginalLen(dataBuf);
1266 memcpy(arrObj->contents, dataBuf, len);
1270 result = (u1*) freeGuardedCopy(dataBuf);
1272 result = (u1*) getGuardedCopyOriginalPtr(dataBuf);
1275 /* pointer is to the array contents; back up to the array object */
1276 result -= offsetof(ArrayObject, contents);
1283 * ===========================================================================
1285 * ===========================================================================
1288 static jint Check_GetVersion(JNIEnv* env)
1290 CHECK_ENTER(env, kFlag_Default);
1292 result = BASE_ENV(env)->GetVersion(env);
1297 static jclass Check_DefineClass(JNIEnv* env, const char* name, jobject loader,
1298 const jbyte* buf, jsize bufLen)
1300 CHECK_ENTER(env, kFlag_Default);
1301 CHECK_OBJECT(env, loader);
1302 CHECK_UTF_STRING(env, name);
1303 CHECK_CLASS_NAME(env, name);
1305 result = BASE_ENV(env)->DefineClass(env, name, loader, buf, bufLen);
1310 static jclass Check_FindClass(JNIEnv* env, const char* name)
1312 CHECK_ENTER(env, kFlag_Default);
1313 CHECK_UTF_STRING(env, name);
1314 CHECK_CLASS_NAME(env, name);
1316 result = BASE_ENV(env)->FindClass(env, name);
1321 static jclass Check_GetSuperclass(JNIEnv* env, jclass clazz)
1323 CHECK_ENTER(env, kFlag_Default);
1324 CHECK_CLASS(env, clazz);
1326 result = BASE_ENV(env)->GetSuperclass(env, clazz);
1331 static jboolean Check_IsAssignableFrom(JNIEnv* env, jclass clazz1,
1334 CHECK_ENTER(env, kFlag_Default);
1335 CHECK_CLASS(env, clazz1);
1336 CHECK_CLASS(env, clazz2);
1338 result = BASE_ENV(env)->IsAssignableFrom(env, clazz1, clazz2);
1343 static jmethodID Check_FromReflectedMethod(JNIEnv* env, jobject method)
1345 CHECK_ENTER(env, kFlag_Default);
1346 CHECK_OBJECT(env, method);
1348 result = BASE_ENV(env)->FromReflectedMethod(env, method);
1353 static jfieldID Check_FromReflectedField(JNIEnv* env, jobject field)
1355 CHECK_ENTER(env, kFlag_Default);
1356 CHECK_OBJECT(env, field);
1358 result = BASE_ENV(env)->FromReflectedField(env, field);
1363 static jobject Check_ToReflectedMethod(JNIEnv* env, jclass cls,
1364 jmethodID methodID, jboolean isStatic)
1366 CHECK_ENTER(env, kFlag_Default);
1367 CHECK_CLASS(env, cls);
1369 result = BASE_ENV(env)->ToReflectedMethod(env, cls, methodID, isStatic);
1374 static jobject Check_ToReflectedField(JNIEnv* env, jclass cls, jfieldID fieldID,
1377 CHECK_ENTER(env, kFlag_Default);
1378 CHECK_CLASS(env, cls);
1380 result = BASE_ENV(env)->ToReflectedField(env, cls, fieldID, isStatic);
1385 static jint Check_Throw(JNIEnv* env, jthrowable obj)
1387 CHECK_ENTER(env, kFlag_Default);
1388 CHECK_OBJECT(env, obj);
1390 result = BASE_ENV(env)->Throw(env, obj);
1395 static jint Check_ThrowNew(JNIEnv* env, jclass clazz, const char* message)
1397 CHECK_ENTER(env, kFlag_Default);
1398 CHECK_CLASS(env, clazz);
1399 CHECK_NULLABLE_UTF_STRING(env, message);
1401 result = BASE_ENV(env)->ThrowNew(env, clazz, message);
1406 static jthrowable Check_ExceptionOccurred(JNIEnv* env)
1408 CHECK_ENTER(env, kFlag_ExcepOkay);
1410 result = BASE_ENV(env)->ExceptionOccurred(env);
1415 static void Check_ExceptionDescribe(JNIEnv* env)
1417 CHECK_ENTER(env, kFlag_ExcepOkay);
1418 BASE_ENV(env)->ExceptionDescribe(env);
1422 static void Check_ExceptionClear(JNIEnv* env)
1424 CHECK_ENTER(env, kFlag_ExcepOkay);
1425 BASE_ENV(env)->ExceptionClear(env);
1429 static void Check_FatalError(JNIEnv* env, const char* msg)
1431 CHECK_ENTER(env, kFlag_Default);
1432 CHECK_NULLABLE_UTF_STRING(env, msg);
1433 BASE_ENV(env)->FatalError(env, msg);
1437 static jint Check_PushLocalFrame(JNIEnv* env, jint capacity)
1439 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1441 result = BASE_ENV(env)->PushLocalFrame(env, capacity);
1446 static jobject Check_PopLocalFrame(JNIEnv* env, jobject res)
1448 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1449 CHECK_OBJECT(env, res);
1451 result = BASE_ENV(env)->PopLocalFrame(env, res);
1456 static jobject Check_NewGlobalRef(JNIEnv* env, jobject obj)
1458 CHECK_ENTER(env, kFlag_Default);
1459 CHECK_OBJECT(env, obj);
1461 result = BASE_ENV(env)->NewGlobalRef(env, obj);
1466 static void Check_DeleteGlobalRef(JNIEnv* env, jobject globalRef)
1468 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1469 CHECK_OBJECT(env, globalRef);
1470 #ifdef USE_INDIRECT_REF
1471 if (globalRef != NULL &&
1472 dvmGetJNIRefType(env, globalRef) != JNIGlobalRefType)
1474 LOGW("JNI WARNING: DeleteGlobalRef on non-global %p (type=%d)",
1475 globalRef, dvmGetJNIRefType(env, globalRef));
1480 BASE_ENV(env)->DeleteGlobalRef(env, globalRef);
1485 static jobject Check_NewLocalRef(JNIEnv* env, jobject ref)
1487 CHECK_ENTER(env, kFlag_Default);
1488 CHECK_OBJECT(env, ref);
1490 result = BASE_ENV(env)->NewLocalRef(env, ref);
1495 static void Check_DeleteLocalRef(JNIEnv* env, jobject localRef)
1497 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1498 CHECK_OBJECT(env, localRef);
1499 #ifdef USE_INDIRECT_REF
1500 if (localRef != NULL &&
1501 dvmGetJNIRefType(env, localRef) != JNILocalRefType)
1503 LOGW("JNI WARNING: DeleteLocalRef on non-local %p (type=%d)",
1504 localRef, dvmGetJNIRefType(env, localRef));
1509 BASE_ENV(env)->DeleteLocalRef(env, localRef);
1514 static jint Check_EnsureLocalCapacity(JNIEnv *env, jint capacity)
1516 CHECK_ENTER(env, kFlag_Default);
1518 result = BASE_ENV(env)->EnsureLocalCapacity(env, capacity);
1523 static jboolean Check_IsSameObject(JNIEnv* env, jobject ref1, jobject ref2)
1525 CHECK_ENTER(env, kFlag_Default);
1526 CHECK_OBJECT(env, ref1);
1527 CHECK_OBJECT(env, ref2);
1529 result = BASE_ENV(env)->IsSameObject(env, ref1, ref2);
1534 static jobject Check_AllocObject(JNIEnv* env, jclass clazz)
1536 CHECK_ENTER(env, kFlag_Default);
1537 CHECK_CLASS(env, clazz);
1539 result = BASE_ENV(env)->AllocObject(env, clazz);
1544 static jobject Check_NewObject(JNIEnv* env, jclass clazz, jmethodID methodID,
1547 CHECK_ENTER(env, kFlag_Default);
1548 CHECK_CLASS(env, clazz);
1550 va_list args, tmpArgs;
1552 va_start(args, methodID);
1554 va_copy(tmpArgs, args);
1555 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);
1558 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1564 static jobject Check_NewObjectV(JNIEnv* env, jclass clazz, jmethodID methodID,
1567 CHECK_ENTER(env, kFlag_Default);
1568 CHECK_CLASS(env, clazz);
1572 va_copy(tmpArgs, args);
1573 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs);
1576 result = BASE_ENV(env)->NewObjectV(env, clazz, methodID, args);
1580 static jobject Check_NewObjectA(JNIEnv* env, jclass clazz, jmethodID methodID,
1583 CHECK_ENTER(env, kFlag_Default);
1584 CHECK_CLASS(env, clazz);
1587 CHECK_METHOD_ARGS_A(env, methodID, args);
1588 result = BASE_ENV(env)->NewObjectA(env, clazz, methodID, args);
1593 static jclass Check_GetObjectClass(JNIEnv* env, jobject obj)
1595 CHECK_ENTER(env, kFlag_Default);
1596 CHECK_OBJECT(env, obj);
1598 result = BASE_ENV(env)->GetObjectClass(env, obj);
1603 static jboolean Check_IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz)
1605 CHECK_ENTER(env, kFlag_Default);
1606 CHECK_OBJECT(env, obj);
1607 CHECK_CLASS(env, clazz);
1609 result = BASE_ENV(env)->IsInstanceOf(env, obj, clazz);
1614 static jmethodID Check_GetMethodID(JNIEnv* env, jclass clazz, const char* name,
1617 CHECK_ENTER(env, kFlag_Default);
1618 CHECK_CLASS(env, clazz);
1619 CHECK_UTF_STRING(env, name);
1620 CHECK_UTF_STRING(env, sig);
1622 result = BASE_ENV(env)->GetMethodID(env, clazz, name, sig);
1627 static jfieldID Check_GetFieldID(JNIEnv* env, jclass clazz,
1628 const char* name, const char* sig)
1630 CHECK_ENTER(env, kFlag_Default);
1631 CHECK_CLASS(env, clazz);
1632 CHECK_UTF_STRING(env, name);
1633 CHECK_UTF_STRING(env, sig);
1635 result = BASE_ENV(env)->GetFieldID(env, clazz, name, sig);
1640 static jmethodID Check_GetStaticMethodID(JNIEnv* env, jclass clazz,
1641 const char* name, const char* sig)
1643 CHECK_ENTER(env, kFlag_Default);
1644 CHECK_CLASS(env, clazz);
1645 CHECK_UTF_STRING(env, name);
1646 CHECK_UTF_STRING(env, sig);
1648 result = BASE_ENV(env)->GetStaticMethodID(env, clazz, name, sig);
1653 static jfieldID Check_GetStaticFieldID(JNIEnv* env, jclass clazz,
1654 const char* name, const char* sig)
1656 CHECK_ENTER(env, kFlag_Default);
1657 CHECK_CLASS(env, clazz);
1658 CHECK_UTF_STRING(env, name);
1659 CHECK_UTF_STRING(env, sig);
1661 result = BASE_ENV(env)->GetStaticFieldID(env, clazz, name, sig);
1666 #define GET_STATIC_TYPE_FIELD(_ctype, _jname) \
1667 static _ctype Check_GetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1670 CHECK_ENTER(env, kFlag_Default); \
1671 CHECK_CLASS(env, clazz); \
1673 checkStaticFieldID(env, clazz, fieldID); \
1674 result = BASE_ENV(env)->GetStatic##_jname##Field(env, clazz, \
1679 GET_STATIC_TYPE_FIELD(jobject, Object);
1680 GET_STATIC_TYPE_FIELD(jboolean, Boolean);
1681 GET_STATIC_TYPE_FIELD(jbyte, Byte);
1682 GET_STATIC_TYPE_FIELD(jchar, Char);
1683 GET_STATIC_TYPE_FIELD(jshort, Short);
1684 GET_STATIC_TYPE_FIELD(jint, Int);
1685 GET_STATIC_TYPE_FIELD(jlong, Long);
1686 GET_STATIC_TYPE_FIELD(jfloat, Float);
1687 GET_STATIC_TYPE_FIELD(jdouble, Double);
1689 #define SET_STATIC_TYPE_FIELD(_ctype, _jname, _ftype) \
1690 static void Check_SetStatic##_jname##Field(JNIEnv* env, jclass clazz, \
1691 jfieldID fieldID, _ctype value) \
1693 CHECK_ENTER(env, kFlag_Default); \
1694 CHECK_CLASS(env, clazz); \
1695 checkStaticFieldID(env, clazz, fieldID); \
1696 /* "value" arg only used when type == ref */ \
1697 CHECK_FIELD_TYPE(env, (jobject)(u4)value, fieldID, _ftype, true); \
1698 BASE_ENV(env)->SetStatic##_jname##Field(env, clazz, fieldID, \
1702 SET_STATIC_TYPE_FIELD(jobject, Object, PRIM_NOT);
1703 SET_STATIC_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1704 SET_STATIC_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1705 SET_STATIC_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1706 SET_STATIC_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1707 SET_STATIC_TYPE_FIELD(jint, Int, PRIM_INT);
1708 SET_STATIC_TYPE_FIELD(jlong, Long, PRIM_LONG);
1709 SET_STATIC_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1710 SET_STATIC_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1712 #define GET_TYPE_FIELD(_ctype, _jname) \
1713 static _ctype Check_Get##_jname##Field(JNIEnv* env, jobject obj, \
1716 CHECK_ENTER(env, kFlag_Default); \
1717 CHECK_OBJECT(env, obj); \
1719 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1720 result = BASE_ENV(env)->Get##_jname##Field(env, obj, fieldID); \
1724 GET_TYPE_FIELD(jobject, Object);
1725 GET_TYPE_FIELD(jboolean, Boolean);
1726 GET_TYPE_FIELD(jbyte, Byte);
1727 GET_TYPE_FIELD(jchar, Char);
1728 GET_TYPE_FIELD(jshort, Short);
1729 GET_TYPE_FIELD(jint, Int);
1730 GET_TYPE_FIELD(jlong, Long);
1731 GET_TYPE_FIELD(jfloat, Float);
1732 GET_TYPE_FIELD(jdouble, Double);
1734 #define SET_TYPE_FIELD(_ctype, _jname, _ftype) \
1735 static void Check_Set##_jname##Field(JNIEnv* env, jobject obj, \
1736 jfieldID fieldID, _ctype value) \
1738 CHECK_ENTER(env, kFlag_Default); \
1739 CHECK_OBJECT(env, obj); \
1740 CHECK_INST_FIELD_ID(env, obj, fieldID); \
1741 /* "value" arg only used when type == ref */ \
1742 CHECK_FIELD_TYPE(env, (jobject)(u4) value, fieldID, _ftype, false); \
1743 BASE_ENV(env)->Set##_jname##Field(env, obj, fieldID, value); \
1746 SET_TYPE_FIELD(jobject, Object, PRIM_NOT);
1747 SET_TYPE_FIELD(jboolean, Boolean, PRIM_BOOLEAN);
1748 SET_TYPE_FIELD(jbyte, Byte, PRIM_BYTE);
1749 SET_TYPE_FIELD(jchar, Char, PRIM_CHAR);
1750 SET_TYPE_FIELD(jshort, Short, PRIM_SHORT);
1751 SET_TYPE_FIELD(jint, Int, PRIM_INT);
1752 SET_TYPE_FIELD(jlong, Long, PRIM_LONG);
1753 SET_TYPE_FIELD(jfloat, Float, PRIM_FLOAT);
1754 SET_TYPE_FIELD(jdouble, Double, PRIM_DOUBLE);
1756 #define CALL_VIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1757 static _ctype Check_Call##_jname##Method(JNIEnv* env, jobject obj, \
1758 jmethodID methodID, ...) \
1760 CHECK_ENTER(env, kFlag_Default); \
1761 CHECK_OBJECT(env, obj); \
1762 CHECK_SIG(env, methodID, _retsig, false); \
1763 CHECK_VIRTUAL_METHOD(env, obj, methodID); \
1765 va_list args, tmpArgs; \
1766 va_start(args, methodID); \
1767 va_copy(tmpArgs, args); \
1768 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1770 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1776 static _ctype Check_Call##_jname##MethodV(JNIEnv* env, jobject obj, \
1777 jmethodID methodID, va_list args) \
1779 CHECK_ENTER(env, kFlag_Default); \
1780 CHECK_OBJECT(env, obj); \
1781 CHECK_SIG(env, methodID, _retsig, false); \
1782 CHECK_VIRTUAL_METHOD(env, obj, methodID); \
1785 va_copy(tmpArgs, args); \
1786 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1788 _retasgn BASE_ENV(env)->Call##_jname##MethodV(env, obj, methodID, \
1793 static _ctype Check_Call##_jname##MethodA(JNIEnv* env, jobject obj, \
1794 jmethodID methodID, jvalue* args) \
1796 CHECK_ENTER(env, kFlag_Default); \
1797 CHECK_OBJECT(env, obj); \
1798 CHECK_SIG(env, methodID, _retsig, false); \
1799 CHECK_VIRTUAL_METHOD(env, obj, methodID); \
1801 CHECK_METHOD_ARGS_A(env, methodID, args); \
1802 _retasgn BASE_ENV(env)->Call##_jname##MethodA(env, obj, methodID, \
1807 CALL_VIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1808 CALL_VIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1809 CALL_VIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1810 CALL_VIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1811 CALL_VIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1812 CALL_VIRTUAL(jint, Int, jint result, result=, result, 'I');
1813 CALL_VIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1814 CALL_VIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1815 CALL_VIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1816 CALL_VIRTUAL(void, Void, , , , 'V');
1818 #define CALL_NONVIRTUAL(_ctype, _jname, _retdecl, _retasgn, _retok, \
1820 static _ctype Check_CallNonvirtual##_jname##Method(JNIEnv* env, \
1821 jobject obj, jclass clazz, jmethodID methodID, ...) \
1823 CHECK_ENTER(env, kFlag_Default); \
1824 CHECK_CLASS(env, clazz); \
1825 CHECK_OBJECT(env, obj); \
1826 CHECK_SIG(env, methodID, _retsig, false); \
1827 CHECK_VIRTUAL_METHOD(env, obj, methodID); \
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)->CallNonvirtual##_jname##MethodV(env, obj, \
1835 clazz, methodID, args); \
1840 static _ctype Check_CallNonvirtual##_jname##MethodV(JNIEnv* env, \
1841 jobject obj, jclass clazz, jmethodID methodID, va_list args) \
1843 CHECK_ENTER(env, kFlag_Default); \
1844 CHECK_CLASS(env, clazz); \
1845 CHECK_OBJECT(env, obj); \
1846 CHECK_SIG(env, methodID, _retsig, false); \
1847 CHECK_VIRTUAL_METHOD(env, obj, methodID); \
1850 va_copy(tmpArgs, args); \
1851 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1853 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodV(env, obj, \
1854 clazz, methodID, args); \
1858 static _ctype Check_CallNonvirtual##_jname##MethodA(JNIEnv* env, \
1859 jobject obj, jclass clazz, jmethodID methodID, jvalue* args) \
1861 CHECK_ENTER(env, kFlag_Default); \
1862 CHECK_CLASS(env, clazz); \
1863 CHECK_OBJECT(env, obj); \
1864 CHECK_SIG(env, methodID, _retsig, false); \
1865 CHECK_VIRTUAL_METHOD(env, obj, methodID); \
1867 CHECK_METHOD_ARGS_A(env, methodID, args); \
1868 _retasgn BASE_ENV(env)->CallNonvirtual##_jname##MethodA(env, obj, \
1869 clazz, methodID, args); \
1873 CALL_NONVIRTUAL(jobject, Object, Object* result, result=, result, 'L');
1874 CALL_NONVIRTUAL(jboolean, Boolean, jboolean result, result=, result, 'Z');
1875 CALL_NONVIRTUAL(jbyte, Byte, jbyte result, result=, result, 'B');
1876 CALL_NONVIRTUAL(jchar, Char, jchar result, result=, result, 'C');
1877 CALL_NONVIRTUAL(jshort, Short, jshort result, result=, result, 'S');
1878 CALL_NONVIRTUAL(jint, Int, jint result, result=, result, 'I');
1879 CALL_NONVIRTUAL(jlong, Long, jlong result, result=, result, 'J');
1880 CALL_NONVIRTUAL(jfloat, Float, jfloat result, result=, result, 'F');
1881 CALL_NONVIRTUAL(jdouble, Double, jdouble result, result=, result, 'D');
1882 CALL_NONVIRTUAL(void, Void, , , , 'V');
1885 #define CALL_STATIC(_ctype, _jname, _retdecl, _retasgn, _retok, _retsig) \
1886 static _ctype Check_CallStatic##_jname##Method(JNIEnv* env, \
1887 jclass clazz, jmethodID methodID, ...) \
1889 CHECK_ENTER(env, kFlag_Default); \
1890 CHECK_CLASS(env, clazz); \
1891 CHECK_SIG(env, methodID, _retsig, true); \
1892 CHECK_STATIC_METHOD(env, clazz, methodID); \
1894 va_list args, tmpArgs; \
1895 va_start(args, methodID); \
1896 va_copy(tmpArgs, args); \
1897 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1899 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1905 static _ctype Check_CallStatic##_jname##MethodV(JNIEnv* env, \
1906 jclass clazz, jmethodID methodID, va_list args) \
1908 CHECK_ENTER(env, kFlag_Default); \
1909 CHECK_CLASS(env, clazz); \
1910 CHECK_SIG(env, methodID, _retsig, true); \
1911 CHECK_STATIC_METHOD(env, clazz, methodID); \
1914 va_copy(tmpArgs, args); \
1915 CHECK_METHOD_ARGS_V(env, methodID, tmpArgs); \
1917 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodV(env, clazz, \
1922 static _ctype Check_CallStatic##_jname##MethodA(JNIEnv* env, \
1923 jclass clazz, jmethodID methodID, jvalue* args) \
1925 CHECK_ENTER(env, kFlag_Default); \
1926 CHECK_CLASS(env, clazz); \
1927 CHECK_SIG(env, methodID, _retsig, true); \
1928 CHECK_STATIC_METHOD(env, clazz, methodID); \
1930 CHECK_METHOD_ARGS_A(env, methodID, args); \
1931 _retasgn BASE_ENV(env)->CallStatic##_jname##MethodA(env, clazz, \
1936 CALL_STATIC(jobject, Object, Object* result, result=, result, 'L');
1937 CALL_STATIC(jboolean, Boolean, jboolean result, result=, result, 'Z');
1938 CALL_STATIC(jbyte, Byte, jbyte result, result=, result, 'B');
1939 CALL_STATIC(jchar, Char, jchar result, result=, result, 'C');
1940 CALL_STATIC(jshort, Short, jshort result, result=, result, 'S');
1941 CALL_STATIC(jint, Int, jint result, result=, result, 'I');
1942 CALL_STATIC(jlong, Long, jlong result, result=, result, 'J');
1943 CALL_STATIC(jfloat, Float, jfloat result, result=, result, 'F');
1944 CALL_STATIC(jdouble, Double, jdouble result, result=, result, 'D');
1945 CALL_STATIC(void, Void, , , , 'V');
1947 static jstring Check_NewString(JNIEnv* env, const jchar* unicodeChars,
1950 CHECK_ENTER(env, kFlag_Default);
1952 result = BASE_ENV(env)->NewString(env, unicodeChars, len);
1957 static jsize Check_GetStringLength(JNIEnv* env, jstring string)
1959 CHECK_ENTER(env, kFlag_CritOkay);
1960 CHECK_STRING(env, string);
1962 result = BASE_ENV(env)->GetStringLength(env, string);
1967 static const jchar* Check_GetStringChars(JNIEnv* env, jstring string,
1970 CHECK_ENTER(env, kFlag_CritOkay);
1971 CHECK_STRING(env, string);
1972 const jchar* result;
1973 result = BASE_ENV(env)->GetStringChars(env, string, isCopy);
1974 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
1975 // TODO: fix for indirect
1976 int len = dvmStringLen(string) * 2;
1977 result = (const jchar*) createGuardedCopy(result, len, false);
1985 static void Check_ReleaseStringChars(JNIEnv* env, jstring string,
1988 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
1989 CHECK_STRING(env, string);
1990 CHECK_NON_NULL(env, chars);
1991 if (((JNIEnvExt*)env)->forceDataCopy) {
1992 if (!checkGuardedCopy(chars, false)) {
1993 LOGE("JNI: failed guarded copy check in ReleaseStringChars");
1997 chars = (const jchar*) freeGuardedCopy((jchar*)chars);
1999 BASE_ENV(env)->ReleaseStringChars(env, string, chars);
2003 static jstring Check_NewStringUTF(JNIEnv* env, const char* bytes)
2005 CHECK_ENTER(env, kFlag_Default);
2006 CHECK_NULLABLE_UTF_STRING(env, bytes);
2008 result = BASE_ENV(env)->NewStringUTF(env, bytes);
2013 static jsize Check_GetStringUTFLength(JNIEnv* env, jstring string)
2015 CHECK_ENTER(env, kFlag_CritOkay);
2016 CHECK_STRING(env, string);
2018 result = BASE_ENV(env)->GetStringUTFLength(env, string);
2023 static const char* Check_GetStringUTFChars(JNIEnv* env, jstring string,
2026 CHECK_ENTER(env, kFlag_CritOkay);
2027 CHECK_STRING(env, string);
2029 result = BASE_ENV(env)->GetStringUTFChars(env, string, isCopy);
2030 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2031 // TODO: fix for indirect
2032 int len = dvmStringUtf8ByteLen(string) + 1;
2033 result = (const char*) createGuardedCopy(result, len, false);
2041 static void Check_ReleaseStringUTFChars(JNIEnv* env, jstring string,
2044 CHECK_ENTER(env, kFlag_ExcepOkay);
2045 CHECK_STRING(env, string);
2046 CHECK_NON_NULL(env, utf);
2047 if (((JNIEnvExt*)env)->forceDataCopy) {
2048 //int len = dvmStringUtf8ByteLen(string) + 1;
2049 if (!checkGuardedCopy(utf, false)) {
2050 LOGE("JNI: failed guarded copy check in ReleaseStringUTFChars");
2054 utf = (const char*) freeGuardedCopy((char*)utf);
2056 BASE_ENV(env)->ReleaseStringUTFChars(env, string, utf);
2060 static jsize Check_GetArrayLength(JNIEnv* env, jarray array)
2062 CHECK_ENTER(env, kFlag_CritOkay);
2063 CHECK_ARRAY(env, array);
2065 result = BASE_ENV(env)->GetArrayLength(env, array);
2070 static jobjectArray Check_NewObjectArray(JNIEnv* env, jsize length,
2071 jclass elementClass, jobject initialElement)
2073 CHECK_ENTER(env, kFlag_Default);
2074 CHECK_CLASS(env, elementClass);
2075 CHECK_OBJECT(env, initialElement);
2076 CHECK_LENGTH_POSITIVE(env, length);
2077 jobjectArray result;
2078 result = BASE_ENV(env)->NewObjectArray(env, length, elementClass,
2084 static jobject Check_GetObjectArrayElement(JNIEnv* env, jobjectArray array,
2087 CHECK_ENTER(env, kFlag_Default);
2088 CHECK_ARRAY(env, array);
2090 result = BASE_ENV(env)->GetObjectArrayElement(env, array, index);
2095 static void Check_SetObjectArrayElement(JNIEnv* env, jobjectArray array,
2096 jsize index, jobject value)
2098 CHECK_ENTER(env, kFlag_Default);
2099 CHECK_ARRAY(env, array);
2100 BASE_ENV(env)->SetObjectArrayElement(env, array, index, value);
2104 #define NEW_PRIMITIVE_ARRAY(_artype, _jname) \
2105 static _artype Check_New##_jname##Array(JNIEnv* env, jsize length) \
2107 CHECK_ENTER(env, kFlag_Default); \
2108 CHECK_LENGTH_POSITIVE(env, length); \
2110 result = BASE_ENV(env)->New##_jname##Array(env, length); \
2114 NEW_PRIMITIVE_ARRAY(jbooleanArray, Boolean);
2115 NEW_PRIMITIVE_ARRAY(jbyteArray, Byte);
2116 NEW_PRIMITIVE_ARRAY(jcharArray, Char);
2117 NEW_PRIMITIVE_ARRAY(jshortArray, Short);
2118 NEW_PRIMITIVE_ARRAY(jintArray, Int);
2119 NEW_PRIMITIVE_ARRAY(jlongArray, Long);
2120 NEW_PRIMITIVE_ARRAY(jfloatArray, Float);
2121 NEW_PRIMITIVE_ARRAY(jdoubleArray, Double);
2125 * Hack to allow forcecopy to work with jniGetNonMovableArrayElements.
2126 * The code deliberately uses an invalid sequence of operations, so we
2127 * need to pass it through unmodified. Review that code before making
2130 #define kNoCopyMagic 0xd5aab57f
2132 #define GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
2133 static _ctype* Check_Get##_jname##ArrayElements(JNIEnv* env, \
2134 _ctype##Array array, jboolean* isCopy) \
2136 CHECK_ENTER(env, kFlag_Default); \
2137 CHECK_ARRAY(env, array); \
2140 if (((JNIEnvExt*)env)->forceDataCopy && isCopy != NULL) { \
2141 /* capture this before the base call tramples on it */ \
2142 noCopy = *(u4*) isCopy; \
2144 result = BASE_ENV(env)->Get##_jname##ArrayElements(env, \
2146 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) { \
2147 if (noCopy == kNoCopyMagic) { \
2148 LOGV("FC: not copying %p %x\n", array, noCopy); \
2150 result = (_ctype*) createGuardedPACopy(env, array, isCopy); \
2157 #define RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname) \
2158 static void Check_Release##_jname##ArrayElements(JNIEnv* env, \
2159 _ctype##Array array, _ctype* elems, jint mode) \
2161 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay); \
2162 CHECK_ARRAY(env, array); \
2163 CHECK_NON_NULL(env, elems); \
2164 CHECK_RELEASE_MODE(env, mode); \
2165 if (((JNIEnvExt*)env)->forceDataCopy) { \
2166 if ((uintptr_t)elems == kNoCopyMagic) { \
2167 LOGV("FC: not freeing %p\n", array); \
2168 elems = NULL; /* base JNI call doesn't currently need */ \
2170 elems = (_ctype*) releaseGuardedPACopy(env, array, elems, \
2174 BASE_ENV(env)->Release##_jname##ArrayElements(env, \
2175 array, elems, mode); \
2179 #define GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
2180 static void Check_Get##_jname##ArrayRegion(JNIEnv* env, \
2181 _ctype##Array array, jsize start, jsize len, _ctype* buf) \
2183 CHECK_ENTER(env, kFlag_Default); \
2184 CHECK_ARRAY(env, array); \
2185 BASE_ENV(env)->Get##_jname##ArrayRegion(env, array, start, \
2190 #define SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname) \
2191 static void Check_Set##_jname##ArrayRegion(JNIEnv* env, \
2192 _ctype##Array array, jsize start, jsize len, const _ctype* buf) \
2194 CHECK_ENTER(env, kFlag_Default); \
2195 CHECK_ARRAY(env, array); \
2196 BASE_ENV(env)->Set##_jname##ArrayRegion(env, array, start, \
2201 #define PRIMITIVE_ARRAY_FUNCTIONS(_ctype, _jname, _typechar) \
2202 GET_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
2203 RELEASE_PRIMITIVE_ARRAY_ELEMENTS(_ctype, _jname); \
2204 GET_PRIMITIVE_ARRAY_REGION(_ctype, _jname); \
2205 SET_PRIMITIVE_ARRAY_REGION(_ctype, _jname);
2207 /* TODO: verify primitive array type matches call type */
2208 PRIMITIVE_ARRAY_FUNCTIONS(jboolean, Boolean, 'Z');
2209 PRIMITIVE_ARRAY_FUNCTIONS(jbyte, Byte, 'B');
2210 PRIMITIVE_ARRAY_FUNCTIONS(jchar, Char, 'C');
2211 PRIMITIVE_ARRAY_FUNCTIONS(jshort, Short, 'S');
2212 PRIMITIVE_ARRAY_FUNCTIONS(jint, Int, 'I');
2213 PRIMITIVE_ARRAY_FUNCTIONS(jlong, Long, 'J');
2214 PRIMITIVE_ARRAY_FUNCTIONS(jfloat, Float, 'F');
2215 PRIMITIVE_ARRAY_FUNCTIONS(jdouble, Double, 'D');
2217 static jint Check_RegisterNatives(JNIEnv* env, jclass clazz,
2218 const JNINativeMethod* methods, jint nMethods)
2220 CHECK_ENTER(env, kFlag_Default);
2221 CHECK_CLASS(env, clazz);
2223 result = BASE_ENV(env)->RegisterNatives(env, clazz, methods, nMethods);
2228 static jint Check_UnregisterNatives(JNIEnv* env, jclass clazz)
2230 CHECK_ENTER(env, kFlag_Default);
2231 CHECK_CLASS(env, clazz);
2233 result = BASE_ENV(env)->UnregisterNatives(env, clazz);
2238 static jint Check_MonitorEnter(JNIEnv* env, jobject obj)
2240 CHECK_ENTER(env, kFlag_Default);
2241 CHECK_OBJECT(env, obj);
2243 result = BASE_ENV(env)->MonitorEnter(env, obj);
2248 static jint Check_MonitorExit(JNIEnv* env, jobject obj)
2250 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2251 CHECK_OBJECT(env, obj);
2253 result = BASE_ENV(env)->MonitorExit(env, obj);
2258 static jint Check_GetJavaVM(JNIEnv *env, JavaVM **vm)
2260 CHECK_ENTER(env, kFlag_Default);
2262 result = BASE_ENV(env)->GetJavaVM(env, vm);
2267 static void Check_GetStringRegion(JNIEnv* env, jstring str, jsize start,
2268 jsize len, jchar* buf)
2270 CHECK_ENTER(env, kFlag_CritOkay);
2271 CHECK_STRING(env, str);
2272 BASE_ENV(env)->GetStringRegion(env, str, start, len, buf);
2276 static void Check_GetStringUTFRegion(JNIEnv* env, jstring str, jsize start,
2277 jsize len, char* buf)
2279 CHECK_ENTER(env, kFlag_CritOkay);
2280 CHECK_STRING(env, str);
2281 BASE_ENV(env)->GetStringUTFRegion(env, str, start, len, buf);
2285 static void* Check_GetPrimitiveArrayCritical(JNIEnv* env, jarray array,
2288 CHECK_ENTER(env, kFlag_CritGet);
2289 CHECK_ARRAY(env, array);
2291 result = BASE_ENV(env)->GetPrimitiveArrayCritical(env, array, isCopy);
2292 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2293 result = createGuardedPACopy(env, array, isCopy);
2299 static void Check_ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array,
2300 void* carray, jint mode)
2302 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2303 CHECK_ARRAY(env, array);
2304 CHECK_NON_NULL(env, carray);
2305 CHECK_RELEASE_MODE(env, mode);
2306 if (((JNIEnvExt*)env)->forceDataCopy) {
2307 carray = releaseGuardedPACopy(env, array, carray, mode);
2309 BASE_ENV(env)->ReleasePrimitiveArrayCritical(env, array, carray, mode);
2313 static const jchar* Check_GetStringCritical(JNIEnv* env, jstring string,
2316 CHECK_ENTER(env, kFlag_CritGet);
2317 CHECK_STRING(env, string);
2318 const jchar* result;
2319 result = BASE_ENV(env)->GetStringCritical(env, string, isCopy);
2320 if (((JNIEnvExt*)env)->forceDataCopy && result != NULL) {
2321 // TODO: fix for indirect
2322 int len = dvmStringLen(string) * 2;
2323 result = (const jchar*) createGuardedCopy(result, len, false);
2331 static void Check_ReleaseStringCritical(JNIEnv* env, jstring string,
2332 const jchar* carray)
2334 CHECK_ENTER(env, kFlag_CritRelease | kFlag_ExcepOkay);
2335 CHECK_STRING(env, string);
2336 CHECK_NON_NULL(env, carray);
2337 if (((JNIEnvExt*)env)->forceDataCopy) {
2338 if (!checkGuardedCopy(carray, false)) {
2339 LOGE("JNI: failed guarded copy check in ReleaseStringCritical");
2343 carray = (const jchar*) freeGuardedCopy((jchar*)carray);
2345 BASE_ENV(env)->ReleaseStringCritical(env, string, carray);
2349 static jweak Check_NewWeakGlobalRef(JNIEnv* env, jobject obj)
2351 CHECK_ENTER(env, kFlag_Default);
2352 CHECK_OBJECT(env, obj);
2354 result = BASE_ENV(env)->NewWeakGlobalRef(env, obj);
2359 static void Check_DeleteWeakGlobalRef(JNIEnv* env, jweak obj)
2361 CHECK_ENTER(env, kFlag_Default | kFlag_ExcepOkay);
2362 CHECK_OBJECT(env, obj);
2363 BASE_ENV(env)->DeleteWeakGlobalRef(env, obj);
2367 static jboolean Check_ExceptionCheck(JNIEnv* env)
2369 CHECK_ENTER(env, kFlag_CritOkay | kFlag_ExcepOkay);
2371 result = BASE_ENV(env)->ExceptionCheck(env);
2376 static jobjectRefType Check_GetObjectRefType(JNIEnv* env, jobject obj)
2378 CHECK_ENTER(env, kFlag_Default);
2379 CHECK_OBJECT(env, obj);
2380 jobjectRefType result;
2381 result = BASE_ENV(env)->GetObjectRefType(env, obj);
2386 static jobject Check_NewDirectByteBuffer(JNIEnv* env, void* address,
2389 CHECK_ENTER(env, kFlag_Default);
2391 if (address == NULL || capacity < 0) {
2392 LOGW("JNI WARNING: invalid values for address (%p) or capacity (%ld)",
2393 address, (long) capacity);
2397 result = BASE_ENV(env)->NewDirectByteBuffer(env, address, capacity);
2402 static void* Check_GetDirectBufferAddress(JNIEnv* env, jobject buf)
2404 CHECK_ENTER(env, kFlag_Default);
2405 CHECK_OBJECT(env, buf);
2406 void* result = BASE_ENV(env)->GetDirectBufferAddress(env, buf);
2411 static jlong Check_GetDirectBufferCapacity(JNIEnv* env, jobject buf)
2413 CHECK_ENTER(env, kFlag_Default);
2414 CHECK_OBJECT(env, buf);
2415 /* TODO: verify "buf" is an instance of java.nio.Buffer */
2416 jlong result = BASE_ENV(env)->GetDirectBufferCapacity(env, buf);
2423 * ===========================================================================
2424 * JNI invocation functions
2425 * ===========================================================================
2428 static jint Check_DestroyJavaVM(JavaVM* vm)
2430 CHECK_VMENTER(vm, false);
2432 result = BASE_VM(vm)->DestroyJavaVM(vm);
2433 CHECK_VMEXIT(vm, false);
2437 static jint Check_AttachCurrentThread(JavaVM* vm, JNIEnv** p_env,
2440 CHECK_VMENTER(vm, false);
2442 result = BASE_VM(vm)->AttachCurrentThread(vm, p_env, thr_args);
2443 CHECK_VMEXIT(vm, true);
2447 static jint Check_AttachCurrentThreadAsDaemon(JavaVM* vm, JNIEnv** p_env,
2450 CHECK_VMENTER(vm, false);
2452 result = BASE_VM(vm)->AttachCurrentThreadAsDaemon(vm, p_env, thr_args);
2453 CHECK_VMEXIT(vm, true);
2457 static jint Check_DetachCurrentThread(JavaVM* vm)
2459 CHECK_VMENTER(vm, true);
2461 result = BASE_VM(vm)->DetachCurrentThread(vm);
2462 CHECK_VMEXIT(vm, false);
2466 static jint Check_GetEnv(JavaVM* vm, void** env, jint version)
2468 CHECK_VMENTER(vm, true);
2470 result = BASE_VM(vm)->GetEnv(vm, env, version);
2471 CHECK_VMEXIT(vm, true);
2477 * ===========================================================================
2479 * ===========================================================================
2482 static const struct JNINativeInterface gCheckNativeInterface = {
2493 Check_FromReflectedMethod,
2494 Check_FromReflectedField,
2495 Check_ToReflectedMethod,
2497 Check_GetSuperclass,
2498 Check_IsAssignableFrom,
2500 Check_ToReflectedField,
2504 Check_ExceptionOccurred,
2505 Check_ExceptionDescribe,
2506 Check_ExceptionClear,
2509 Check_PushLocalFrame,
2510 Check_PopLocalFrame,
2513 Check_DeleteGlobalRef,
2514 Check_DeleteLocalRef,
2517 Check_EnsureLocalCapacity,
2524 Check_GetObjectClass,
2529 Check_CallObjectMethod,
2530 Check_CallObjectMethodV,
2531 Check_CallObjectMethodA,
2532 Check_CallBooleanMethod,
2533 Check_CallBooleanMethodV,
2534 Check_CallBooleanMethodA,
2535 Check_CallByteMethod,
2536 Check_CallByteMethodV,
2537 Check_CallByteMethodA,
2538 Check_CallCharMethod,
2539 Check_CallCharMethodV,
2540 Check_CallCharMethodA,
2541 Check_CallShortMethod,
2542 Check_CallShortMethodV,
2543 Check_CallShortMethodA,
2544 Check_CallIntMethod,
2545 Check_CallIntMethodV,
2546 Check_CallIntMethodA,
2547 Check_CallLongMethod,
2548 Check_CallLongMethodV,
2549 Check_CallLongMethodA,
2550 Check_CallFloatMethod,
2551 Check_CallFloatMethodV,
2552 Check_CallFloatMethodA,
2553 Check_CallDoubleMethod,
2554 Check_CallDoubleMethodV,
2555 Check_CallDoubleMethodA,
2556 Check_CallVoidMethod,
2557 Check_CallVoidMethodV,
2558 Check_CallVoidMethodA,
2560 Check_CallNonvirtualObjectMethod,
2561 Check_CallNonvirtualObjectMethodV,
2562 Check_CallNonvirtualObjectMethodA,
2563 Check_CallNonvirtualBooleanMethod,
2564 Check_CallNonvirtualBooleanMethodV,
2565 Check_CallNonvirtualBooleanMethodA,
2566 Check_CallNonvirtualByteMethod,
2567 Check_CallNonvirtualByteMethodV,
2568 Check_CallNonvirtualByteMethodA,
2569 Check_CallNonvirtualCharMethod,
2570 Check_CallNonvirtualCharMethodV,
2571 Check_CallNonvirtualCharMethodA,
2572 Check_CallNonvirtualShortMethod,
2573 Check_CallNonvirtualShortMethodV,
2574 Check_CallNonvirtualShortMethodA,
2575 Check_CallNonvirtualIntMethod,
2576 Check_CallNonvirtualIntMethodV,
2577 Check_CallNonvirtualIntMethodA,
2578 Check_CallNonvirtualLongMethod,
2579 Check_CallNonvirtualLongMethodV,
2580 Check_CallNonvirtualLongMethodA,
2581 Check_CallNonvirtualFloatMethod,
2582 Check_CallNonvirtualFloatMethodV,
2583 Check_CallNonvirtualFloatMethodA,
2584 Check_CallNonvirtualDoubleMethod,
2585 Check_CallNonvirtualDoubleMethodV,
2586 Check_CallNonvirtualDoubleMethodA,
2587 Check_CallNonvirtualVoidMethod,
2588 Check_CallNonvirtualVoidMethodV,
2589 Check_CallNonvirtualVoidMethodA,
2593 Check_GetObjectField,
2594 Check_GetBooleanField,
2597 Check_GetShortField,
2600 Check_GetFloatField,
2601 Check_GetDoubleField,
2602 Check_SetObjectField,
2603 Check_SetBooleanField,
2606 Check_SetShortField,
2609 Check_SetFloatField,
2610 Check_SetDoubleField,
2612 Check_GetStaticMethodID,
2614 Check_CallStaticObjectMethod,
2615 Check_CallStaticObjectMethodV,
2616 Check_CallStaticObjectMethodA,
2617 Check_CallStaticBooleanMethod,
2618 Check_CallStaticBooleanMethodV,
2619 Check_CallStaticBooleanMethodA,
2620 Check_CallStaticByteMethod,
2621 Check_CallStaticByteMethodV,
2622 Check_CallStaticByteMethodA,
2623 Check_CallStaticCharMethod,
2624 Check_CallStaticCharMethodV,
2625 Check_CallStaticCharMethodA,
2626 Check_CallStaticShortMethod,
2627 Check_CallStaticShortMethodV,
2628 Check_CallStaticShortMethodA,
2629 Check_CallStaticIntMethod,
2630 Check_CallStaticIntMethodV,
2631 Check_CallStaticIntMethodA,
2632 Check_CallStaticLongMethod,
2633 Check_CallStaticLongMethodV,
2634 Check_CallStaticLongMethodA,
2635 Check_CallStaticFloatMethod,
2636 Check_CallStaticFloatMethodV,
2637 Check_CallStaticFloatMethodA,
2638 Check_CallStaticDoubleMethod,
2639 Check_CallStaticDoubleMethodV,
2640 Check_CallStaticDoubleMethodA,
2641 Check_CallStaticVoidMethod,
2642 Check_CallStaticVoidMethodV,
2643 Check_CallStaticVoidMethodA,
2645 Check_GetStaticFieldID,
2647 Check_GetStaticObjectField,
2648 Check_GetStaticBooleanField,
2649 Check_GetStaticByteField,
2650 Check_GetStaticCharField,
2651 Check_GetStaticShortField,
2652 Check_GetStaticIntField,
2653 Check_GetStaticLongField,
2654 Check_GetStaticFloatField,
2655 Check_GetStaticDoubleField,
2657 Check_SetStaticObjectField,
2658 Check_SetStaticBooleanField,
2659 Check_SetStaticByteField,
2660 Check_SetStaticCharField,
2661 Check_SetStaticShortField,
2662 Check_SetStaticIntField,
2663 Check_SetStaticLongField,
2664 Check_SetStaticFloatField,
2665 Check_SetStaticDoubleField,
2669 Check_GetStringLength,
2670 Check_GetStringChars,
2671 Check_ReleaseStringChars,
2674 Check_GetStringUTFLength,
2675 Check_GetStringUTFChars,
2676 Check_ReleaseStringUTFChars,
2678 Check_GetArrayLength,
2679 Check_NewObjectArray,
2680 Check_GetObjectArrayElement,
2681 Check_SetObjectArrayElement,
2683 Check_NewBooleanArray,
2686 Check_NewShortArray,
2689 Check_NewFloatArray,
2690 Check_NewDoubleArray,
2692 Check_GetBooleanArrayElements,
2693 Check_GetByteArrayElements,
2694 Check_GetCharArrayElements,
2695 Check_GetShortArrayElements,
2696 Check_GetIntArrayElements,
2697 Check_GetLongArrayElements,
2698 Check_GetFloatArrayElements,
2699 Check_GetDoubleArrayElements,
2701 Check_ReleaseBooleanArrayElements,
2702 Check_ReleaseByteArrayElements,
2703 Check_ReleaseCharArrayElements,
2704 Check_ReleaseShortArrayElements,
2705 Check_ReleaseIntArrayElements,
2706 Check_ReleaseLongArrayElements,
2707 Check_ReleaseFloatArrayElements,
2708 Check_ReleaseDoubleArrayElements,
2710 Check_GetBooleanArrayRegion,
2711 Check_GetByteArrayRegion,
2712 Check_GetCharArrayRegion,
2713 Check_GetShortArrayRegion,
2714 Check_GetIntArrayRegion,
2715 Check_GetLongArrayRegion,
2716 Check_GetFloatArrayRegion,
2717 Check_GetDoubleArrayRegion,
2718 Check_SetBooleanArrayRegion,
2719 Check_SetByteArrayRegion,
2720 Check_SetCharArrayRegion,
2721 Check_SetShortArrayRegion,
2722 Check_SetIntArrayRegion,
2723 Check_SetLongArrayRegion,
2724 Check_SetFloatArrayRegion,
2725 Check_SetDoubleArrayRegion,
2727 Check_RegisterNatives,
2728 Check_UnregisterNatives,
2735 Check_GetStringRegion,
2736 Check_GetStringUTFRegion,
2738 Check_GetPrimitiveArrayCritical,
2739 Check_ReleasePrimitiveArrayCritical,
2741 Check_GetStringCritical,
2742 Check_ReleaseStringCritical,
2744 Check_NewWeakGlobalRef,
2745 Check_DeleteWeakGlobalRef,
2747 Check_ExceptionCheck,
2749 Check_NewDirectByteBuffer,
2750 Check_GetDirectBufferAddress,
2751 Check_GetDirectBufferCapacity,
2753 Check_GetObjectRefType
2755 static const struct JNIInvokeInterface gCheckInvokeInterface = {
2760 Check_DestroyJavaVM,
2761 Check_AttachCurrentThread,
2762 Check_DetachCurrentThread,
2766 Check_AttachCurrentThreadAsDaemon,
2771 * Replace the normal table with the checked table.
2773 void dvmUseCheckedJniEnv(JNIEnvExt* pEnv)
2775 assert(pEnv->funcTable != &gCheckNativeInterface);
2776 pEnv->baseFuncTable = pEnv->funcTable;
2777 pEnv->funcTable = &gCheckNativeInterface;
2781 * Replace the normal table with the checked table.
2783 void dvmUseCheckedJniVm(JavaVMExt* pVm)
2785 assert(pVm->funcTable != &gCheckInvokeInterface);
2786 pVm->baseFuncTable = pVm->funcTable;
2787 pVm->funcTable = &gCheckInvokeInterface;