diff options
Diffstat (limited to 'runtime')
| -rw-r--r-- | runtime/check_jni.cc | 2 | ||||
| -rw-r--r-- | runtime/class_linker.cc | 5 | ||||
| -rw-r--r-- | runtime/jni_internal.cc | 606 | ||||
| -rw-r--r-- | runtime/jni_internal_test.cc | 913 | ||||
| -rw-r--r-- | runtime/mirror/array.h | 13 | ||||
| -rw-r--r-- | runtime/native/dalvik_system_VMRuntime.cc | 8 | ||||
| -rw-r--r-- | runtime/parsed_options.cc | 4 |
7 files changed, 967 insertions, 584 deletions
diff --git a/runtime/check_jni.cc b/runtime/check_jni.cc index 0d5a805c8d..cfd0c007f1 100644 --- a/runtime/check_jni.cc +++ b/runtime/check_jni.cc @@ -179,7 +179,7 @@ class ScopedCheck { // times, so using "java.lang.Thread" instead of "java/lang/Thread" might work in some // circumstances, but this is incorrect. void CheckClassName(const char* class_name) { - if (!IsValidJniClassName(class_name)) { + if ((class_name == nullptr) || !IsValidJniClassName(class_name)) { JniAbortF(function_name_, "illegal class name '%s'\n" " (should be of the form 'package/Class', [Lpackage/Class;' or '[[B')", diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc index 3d268e4538..9034560689 100644 --- a/runtime/class_linker.cc +++ b/runtime/class_linker.cc @@ -2215,7 +2215,10 @@ mirror::Class* ClassLinker::CreateArrayClass(Thread* self, const char* descripto DCHECK(self->IsExceptionPending()); return nullptr; } - + if (UNLIKELY(component_type->IsPrimitiveVoid())) { + ThrowNoClassDefFoundError("Attempt to create array of void primitive type"); + return nullptr; + } // See if the component type is already loaded. Array classes are // always associated with the class loader of their underlying // element type -- an array of Strings goes with the loader for diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 46349712ac..21dab8d001 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -518,16 +518,28 @@ class Libraries { SafeMap<std::string, SharedLibrary*> libraries_; }; -#define CHECK_NON_NULL_ARGUMENT(value) CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value) +#define CHECK_NON_NULL_ARGUMENT(value) \ + CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, nullptr) -#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value) \ +#define CHECK_NON_NULL_ARGUMENT_RETURN_VOID(value) \ + CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, ) + +#define CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(value) \ + CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, 0) + +#define CHECK_NON_NULL_ARGUMENT_RETURN(value, return_val) \ + CHECK_NON_NULL_ARGUMENT_FN_NAME(__FUNCTION__, value, return_val) + +#define CHECK_NON_NULL_ARGUMENT_FN_NAME(name, value, return_val) \ if (UNLIKELY(value == nullptr)) { \ JniAbortF(name, #value " == null"); \ + return return_val; \ } #define CHECK_NON_NULL_MEMCPY_ARGUMENT(length, value) \ if (UNLIKELY(length != 0 && value == nullptr)) { \ JniAbortF(__FUNCTION__, #value " == null"); \ + return; \ } class JNI { @@ -614,8 +626,8 @@ class JNI { } static jboolean IsAssignableFrom(JNIEnv* env, jclass java_class1, jclass java_class2) { - CHECK_NON_NULL_ARGUMENT(java_class1); - CHECK_NON_NULL_ARGUMENT(java_class2); + CHECK_NON_NULL_ARGUMENT_RETURN(java_class1, JNI_FALSE); + CHECK_NON_NULL_ARGUMENT_RETURN(java_class2, JNI_FALSE); ScopedObjectAccess soa(env); mirror::Class* c1 = soa.Decode<mirror::Class*>(java_class1); mirror::Class* c2 = soa.Decode<mirror::Class*>(java_class2); @@ -623,7 +635,7 @@ class JNI { } static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) { - CHECK_NON_NULL_ARGUMENT(java_class); + CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_FALSE); if (jobj == nullptr) { // Note: JNI is different from regular Java instanceof in this respect return JNI_TRUE; @@ -647,7 +659,7 @@ class JNI { } static jint ThrowNew(JNIEnv* env, jclass c, const char* msg) { - CHECK_NON_NULL_ARGUMENT(c); + CHECK_NON_NULL_ARGUMENT_RETURN(c, JNI_ERR); return ThrowNewException(env, c, msg, nullptr); } @@ -914,8 +926,8 @@ class JNI { static jboolean CallBooleanMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -923,15 +935,15 @@ class JNI { } static jboolean CallBooleanMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetZ(); } static jboolean CallBooleanMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ(); @@ -940,8 +952,8 @@ class JNI { static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -949,15 +961,15 @@ class JNI { } static jbyte CallByteMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetB(); } static jbyte CallByteMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB(); @@ -966,8 +978,8 @@ class JNI { static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -975,15 +987,15 @@ class JNI { } static jchar CallCharMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetC(); } static jchar CallCharMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC(); @@ -992,8 +1004,8 @@ class JNI { static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1001,15 +1013,15 @@ class JNI { } static jdouble CallDoubleMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetD(); } static jdouble CallDoubleMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD(); @@ -1018,8 +1030,8 @@ class JNI { static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1027,15 +1039,15 @@ class JNI { } static jfloat CallFloatMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetF(); } static jfloat CallFloatMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF(); @@ -1044,8 +1056,8 @@ class JNI { static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1053,15 +1065,15 @@ class JNI { } static jint CallIntMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetI(); } static jint CallIntMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI(); @@ -1070,8 +1082,8 @@ class JNI { static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1079,15 +1091,15 @@ class JNI { } static jlong CallLongMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetJ(); } static jlong CallLongMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ(); @@ -1096,8 +1108,8 @@ class JNI { static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1105,15 +1117,15 @@ class JNI { } static jshort CallShortMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args).GetS(); } static jshort CallShortMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS(); @@ -1122,23 +1134,23 @@ class JNI { static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, ap); va_end(ap); } static void CallVoidMethodV(JNIEnv* env, jobject obj, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeVirtualOrInterfaceWithVarArgs(soa, obj, mid, args); } static void CallVoidMethodA(JNIEnv* env, jobject obj, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args); } @@ -1177,8 +1189,8 @@ class JNI { ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1187,16 +1199,16 @@ class JNI { static jboolean CallNonvirtualBooleanMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetZ(); } static jboolean CallNonvirtualBooleanMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ(); } @@ -1204,8 +1216,8 @@ class JNI { static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1214,16 +1226,16 @@ class JNI { static jbyte CallNonvirtualByteMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetB(); } static jbyte CallNonvirtualByteMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB(); } @@ -1231,8 +1243,8 @@ class JNI { static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1241,16 +1253,16 @@ class JNI { static jchar CallNonvirtualCharMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetC(); } static jchar CallNonvirtualCharMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC(); } @@ -1258,8 +1270,8 @@ class JNI { static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1268,16 +1280,16 @@ class JNI { static jshort CallNonvirtualShortMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetS(); } static jshort CallNonvirtualShortMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS(); } @@ -1285,8 +1297,8 @@ class JNI { static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1295,16 +1307,16 @@ class JNI { static jint CallNonvirtualIntMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetI(); } static jint CallNonvirtualIntMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI(); } @@ -1312,8 +1324,8 @@ class JNI { static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1322,16 +1334,16 @@ class JNI { static jlong CallNonvirtualLongMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetJ(); } static jlong CallNonvirtualLongMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ(); } @@ -1339,8 +1351,8 @@ class JNI { static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1349,16 +1361,16 @@ class JNI { static jfloat CallNonvirtualFloatMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetF(); } static jfloat CallNonvirtualFloatMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF(); } @@ -1366,8 +1378,8 @@ class JNI { static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, obj, mid, ap)); va_end(ap); @@ -1376,16 +1388,16 @@ class JNI { static jdouble CallNonvirtualDoubleMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, obj, mid, args).GetD(); } static jdouble CallNonvirtualDoubleMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD(); } @@ -1393,8 +1405,8 @@ class JNI { static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeWithVarArgs(soa, obj, mid, ap); va_end(ap); @@ -1402,16 +1414,16 @@ class JNI { static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeWithVarArgs(soa, obj, mid, args); } static void CallNonvirtualVoidMethodA(JNIEnv* env, jobject obj, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(obj); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(obj); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args); } @@ -1450,8 +1462,8 @@ class JNI { } static void SetObjectField(JNIEnv* env, jobject java_object, jfieldID fid, jobject java_value) { - CHECK_NON_NULL_ARGUMENT(java_object); - CHECK_NON_NULL_ARGUMENT(fid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_object); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); ScopedObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_object); mirror::Object* v = soa.Decode<mirror::Object*>(java_value); @@ -1460,7 +1472,7 @@ class JNI { } static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) { - CHECK_NON_NULL_ARGUMENT(fid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); ScopedObjectAccess soa(env); mirror::Object* v = soa.Decode<mirror::Object*>(java_value); mirror::ArtField* f = soa.DecodeField(fid); @@ -1468,29 +1480,29 @@ class JNI { } #define GET_PRIMITIVE_FIELD(fn, instance) \ - CHECK_NON_NULL_ARGUMENT(instance); \ - CHECK_NON_NULL_ARGUMENT(fid); \ + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(instance); \ + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ ScopedObjectAccess soa(env); \ mirror::Object* o = soa.Decode<mirror::Object*>(instance); \ mirror::ArtField* f = soa.DecodeField(fid); \ return f->Get ##fn (o) #define GET_STATIC_PRIMITIVE_FIELD(fn) \ - CHECK_NON_NULL_ARGUMENT(fid); \ + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(fid); \ ScopedObjectAccess soa(env); \ mirror::ArtField* f = soa.DecodeField(fid); \ return f->Get ##fn (f->GetDeclaringClass()) #define SET_PRIMITIVE_FIELD(fn, instance, value) \ - CHECK_NON_NULL_ARGUMENT(instance); \ - CHECK_NON_NULL_ARGUMENT(fid); \ + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(instance); \ + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ ScopedObjectAccess soa(env); \ mirror::Object* o = soa.Decode<mirror::Object*>(instance); \ mirror::ArtField* f = soa.DecodeField(fid); \ f->Set ##fn <false>(o, value) #define SET_STATIC_PRIMITIVE_FIELD(fn, value) \ - CHECK_NON_NULL_ARGUMENT(fid); \ + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(fid); \ ScopedObjectAccess soa(env); \ mirror::ArtField* f = soa.DecodeField(fid); \ f->Set ##fn <false>(f->GetDeclaringClass(), value) @@ -1651,7 +1663,7 @@ class JNI { static jboolean CallStaticBooleanMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1659,13 +1671,13 @@ class JNI { } static jboolean CallStaticBooleanMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetZ(); } static jboolean CallStaticBooleanMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetZ(); } @@ -1673,7 +1685,7 @@ class JNI { static jbyte CallStaticByteMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1681,13 +1693,13 @@ class JNI { } static jbyte CallStaticByteMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetB(); } static jbyte CallStaticByteMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetB(); } @@ -1695,7 +1707,7 @@ class JNI { static jchar CallStaticCharMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1703,13 +1715,13 @@ class JNI { } static jchar CallStaticCharMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetC(); } static jchar CallStaticCharMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetC(); } @@ -1717,7 +1729,7 @@ class JNI { static jshort CallStaticShortMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1725,13 +1737,13 @@ class JNI { } static jshort CallStaticShortMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetS(); } static jshort CallStaticShortMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetS(); } @@ -1739,7 +1751,7 @@ class JNI { static jint CallStaticIntMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1747,13 +1759,13 @@ class JNI { } static jint CallStaticIntMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetI(); } static jint CallStaticIntMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetI(); } @@ -1761,7 +1773,7 @@ class JNI { static jlong CallStaticLongMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1769,13 +1781,13 @@ class JNI { } static jlong CallStaticLongMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetJ(); } static jlong CallStaticLongMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetJ(); } @@ -1783,7 +1795,7 @@ class JNI { static jfloat CallStaticFloatMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1791,13 +1803,13 @@ class JNI { } static jfloat CallStaticFloatMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetF(); } static jfloat CallStaticFloatMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetF(); } @@ -1805,7 +1817,7 @@ class JNI { static jdouble CallStaticDoubleMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); JValue result(InvokeWithVarArgs(soa, nullptr, mid, ap)); va_end(ap); @@ -1813,13 +1825,13 @@ class JNI { } static jdouble CallStaticDoubleMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithVarArgs(soa, nullptr, mid, args).GetD(); } static jdouble CallStaticDoubleMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(mid); ScopedObjectAccess soa(env); return InvokeWithJValues(soa, nullptr, mid, args).GetD(); } @@ -1827,20 +1839,20 @@ class JNI { static void CallStaticVoidMethod(JNIEnv* env, jclass, jmethodID mid, ...) { va_list ap; va_start(ap, mid); - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeWithVarArgs(soa, nullptr, mid, ap); va_end(ap); } static void CallStaticVoidMethodV(JNIEnv* env, jclass, jmethodID mid, va_list args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeWithVarArgs(soa, nullptr, mid, args); } static void CallStaticVoidMethodA(JNIEnv* env, jclass, jmethodID mid, jvalue* args) { - CHECK_NON_NULL_ARGUMENT(mid); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(mid); ScopedObjectAccess soa(env); InvokeWithJValues(soa, nullptr, mid, args); } @@ -1869,20 +1881,20 @@ class JNI { } static jsize GetStringLength(JNIEnv* env, jstring java_string) { - CHECK_NON_NULL_ARGUMENT(java_string); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string); ScopedObjectAccess soa(env); return soa.Decode<mirror::String*>(java_string)->GetLength(); } static jsize GetStringUTFLength(JNIEnv* env, jstring java_string) { - CHECK_NON_NULL_ARGUMENT(java_string); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_string); ScopedObjectAccess soa(env); return soa.Decode<mirror::String*>(java_string)->GetUtfLength(); } static void GetStringRegion(JNIEnv* env, jstring java_string, jsize start, jsize length, jchar* buf) { - CHECK_NON_NULL_ARGUMENT(java_string); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string); ScopedObjectAccess soa(env); mirror::String* s = soa.Decode<mirror::String*>(java_string); if (start < 0 || length < 0 || start + length > s->GetLength()) { @@ -1896,7 +1908,7 @@ class JNI { static void GetStringUTFRegion(JNIEnv* env, jstring java_string, jsize start, jsize length, char* buf) { - CHECK_NON_NULL_ARGUMENT(java_string); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string); ScopedObjectAccess soa(env); mirror::String* s = soa.Decode<mirror::String*>(java_string); if (start < 0 || length < 0 || start + length > s->GetLength()) { @@ -1928,7 +1940,7 @@ class JNI { } static void ReleaseStringChars(JNIEnv* env, jstring java_string, const jchar* chars) { - CHECK_NON_NULL_ARGUMENT(java_string); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_string); delete[] chars; ScopedObjectAccess soa(env); UnpinPrimitiveArray(soa, soa.Decode<mirror::String*>(java_string)->GetCharArray()); @@ -1965,7 +1977,7 @@ class JNI { } static jsize GetArrayLength(JNIEnv* env, jarray java_array) { - CHECK_NON_NULL_ARGUMENT(java_array); + CHECK_NON_NULL_ARGUMENT_RETURN_ZERO(java_array); ScopedObjectAccess soa(env); mirror::Object* obj = soa.Decode<mirror::Object*>(java_array); if (UNLIKELY(!obj->IsArrayInstance())) { @@ -1985,7 +1997,7 @@ class JNI { static void SetObjectArrayElement(JNIEnv* env, jobjectArray java_array, jsize index, jobject java_value) { - CHECK_NON_NULL_ARGUMENT(java_array); + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array); ScopedObjectAccess soa(env); mirror::ObjectArray<mirror::Object>* array = soa.Decode<mirror::ObjectArray<mirror::Object>*>(java_array); @@ -1994,38 +2006,31 @@ class JNI { } static jbooleanArray NewBooleanArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jbooleanArray, mirror::BooleanArray>(soa, length); + return NewPrimitiveArray<jbooleanArray, mirror::BooleanArray>(env, length); } static jbyteArray NewByteArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jbyteArray, mirror::ByteArray>(soa, length); + return NewPrimitiveArray<jbyteArray, mirror::ByteArray>(env, length); } static jcharArray NewCharArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jcharArray, mirror::CharArray>(soa, length); + return NewPrimitiveArray<jcharArray, mirror::CharArray>(env, length); } static jdoubleArray NewDoubleArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jdoubleArray, mirror::DoubleArray>(soa, length); + return NewPrimitiveArray<jdoubleArray, mirror::DoubleArray>(env, length); } static jfloatArray NewFloatArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jfloatArray, mirror::FloatArray>(soa, length); + return NewPrimitiveArray<jfloatArray, mirror::FloatArray>(env, length); } static jintArray NewIntArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jintArray, mirror::IntArray>(soa, length); + return NewPrimitiveArray<jintArray, mirror::IntArray>(env, length); } static jlongArray NewLongArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jlongArray, mirror::LongArray>(soa, length); + return NewPrimitiveArray<jlongArray, mirror::LongArray>(env, length); } static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, @@ -2034,6 +2039,7 @@ class JNI { JniAbortF("NewObjectArray", "negative array length: %d", length); return nullptr; } + CHECK_NON_NULL_ARGUMENT(element_jclass); // Compute the array class corresponding to the given element class. ScopedObjectAccess soa(env); @@ -2075,14 +2081,18 @@ class JNI { } static jshortArray NewShortArray(JNIEnv* env, jsize length) { - ScopedObjectAccess soa(env); - return NewPrimitiveArray<jshortArray, mirror::ShortArray>(soa, length); + return NewPrimitiveArray<jshortArray, mirror::ShortArray>(env, length); } static void* GetPrimitiveArrayCritical(JNIEnv* env, jarray java_array, jboolean* is_copy) { CHECK_NON_NULL_ARGUMENT(java_array); ScopedObjectAccess soa(env); mirror::Array* array = soa.Decode<mirror::Array*>(java_array); + if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) { + JniAbortF("GetPrimitiveArrayCritical", "expected primitive array, given %s", + PrettyDescriptor(array->GetClass()).c_str()); + return nullptr; + } gc::Heap* heap = Runtime::Current()->GetHeap(); if (heap->IsMovableObject(array)) { heap->IncrementDisableMovingGC(soa.Self()); @@ -2096,196 +2106,174 @@ class JNI { return array->GetRawData(array->GetClass()->GetComponentSize(), 0); } - static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray array, void* elements, jint mode) { - CHECK_NON_NULL_ARGUMENT(array); - ReleasePrimitiveArray(env, array, elements, mode); + static void ReleasePrimitiveArrayCritical(JNIEnv* env, jarray java_array, void* elements, + jint mode) { + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array); + ScopedObjectAccess soa(env); + mirror::Array* array = soa.Decode<mirror::Array*>(java_array); + if (UNLIKELY(!array->GetClass()->IsPrimitiveArray())) { + JniAbortF("ReleasePrimitiveArrayCritical", "expected primitive array, given %s", + PrettyDescriptor(array->GetClass()).c_str()); + return; + } + const size_t component_size = array->GetClass()->GetComponentSize(); + ReleasePrimitiveArray(soa, array, component_size, elements, mode); } static jboolean* GetBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jbooleanArray, jboolean*, mirror::BooleanArray>(soa, array, is_copy); + return GetPrimitiveArray<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, is_copy); } static jbyte* GetByteArrayElements(JNIEnv* env, jbyteArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jbyteArray, jbyte*, mirror::ByteArray>(soa, array, is_copy); + return GetPrimitiveArray<jbyteArray, jbyte, mirror::ByteArray>(env, array, is_copy); } static jchar* GetCharArrayElements(JNIEnv* env, jcharArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jcharArray, jchar*, mirror::CharArray>(soa, array, is_copy); + return GetPrimitiveArray<jcharArray, jchar, mirror::CharArray>(env, array, is_copy); } static jdouble* GetDoubleArrayElements(JNIEnv* env, jdoubleArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jdoubleArray, jdouble*, mirror::DoubleArray>(soa, array, is_copy); + return GetPrimitiveArray<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, is_copy); } static jfloat* GetFloatArrayElements(JNIEnv* env, jfloatArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jfloatArray, jfloat*, mirror::FloatArray>(soa, array, is_copy); + return GetPrimitiveArray<jfloatArray, jfloat, mirror::FloatArray>(env, array, is_copy); } static jint* GetIntArrayElements(JNIEnv* env, jintArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jintArray, jint*, mirror::IntArray>(soa, array, is_copy); + return GetPrimitiveArray<jintArray, jint, mirror::IntArray>(env, array, is_copy); } static jlong* GetLongArrayElements(JNIEnv* env, jlongArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jlongArray, jlong*, mirror::LongArray>(soa, array, is_copy); + return GetPrimitiveArray<jlongArray, jlong, mirror::LongArray>(env, array, is_copy); } static jshort* GetShortArrayElements(JNIEnv* env, jshortArray array, jboolean* is_copy) { - CHECK_NON_NULL_ARGUMENT(array); - ScopedObjectAccess soa(env); - return GetPrimitiveArray<jshortArray, jshort*, mirror::ShortArray>(soa, array, is_copy); + return GetPrimitiveArray<jshortArray, jshort, mirror::ShortArray>(env, array, is_copy); } static void ReleaseBooleanArrayElements(JNIEnv* env, jbooleanArray array, jboolean* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, elements, + mode); } static void ReleaseByteArrayElements(JNIEnv* env, jbyteArray array, jbyte* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jbyteArray, jbyte, mirror::ByteArray>(env, array, elements, mode); } static void ReleaseCharArrayElements(JNIEnv* env, jcharArray array, jchar* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jcharArray, jchar, mirror::CharArray>(env, array, elements, mode); } static void ReleaseDoubleArrayElements(JNIEnv* env, jdoubleArray array, jdouble* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, elements, mode); } static void ReleaseFloatArrayElements(JNIEnv* env, jfloatArray array, jfloat* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jfloatArray, jfloat, mirror::FloatArray>(env, array, elements, mode); } static void ReleaseIntArrayElements(JNIEnv* env, jintArray array, jint* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jintArray, jint, mirror::IntArray>(env, array, elements, mode); } static void ReleaseLongArrayElements(JNIEnv* env, jlongArray array, jlong* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jlongArray, jlong, mirror::LongArray>(env, array, elements, mode); } static void ReleaseShortArrayElements(JNIEnv* env, jshortArray array, jshort* elements, jint mode) { - ReleasePrimitiveArray(env, array, elements, mode); + ReleasePrimitiveArray<jshortArray, jshort, mirror::ShortArray>(env, array, elements, mode); } static void GetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, jboolean* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(soa, array, start, + GetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, start, length, buf); } static void GetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, jbyte* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(soa, array, start, length, buf); + GetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(env, array, start, length, buf); } static void GetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, jchar* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(soa, array, start, length, buf); + GetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(env, array, start, length, buf); } static void GetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, jdouble* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(soa, array, start, length, + GetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, start, length, buf); } static void GetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, jfloat* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(soa, array, start, length, + GetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(env, array, start, length, buf); } static void GetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, jint* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(soa, array, start, length, buf); + GetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(env, array, start, length, buf); } static void GetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, jlong* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(soa, array, start, length, buf); + GetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(env, array, start, length, buf); } static void GetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, jshort* buf) { - ScopedObjectAccess soa(env); - GetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(soa, array, start, length, + GetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(env, array, start, length, buf); } static void SetBooleanArrayRegion(JNIEnv* env, jbooleanArray array, jsize start, jsize length, const jboolean* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(soa, array, start, + SetPrimitiveArrayRegion<jbooleanArray, jboolean, mirror::BooleanArray>(env, array, start, length, buf); } static void SetByteArrayRegion(JNIEnv* env, jbyteArray array, jsize start, jsize length, const jbyte* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(soa, array, start, length, buf); + SetPrimitiveArrayRegion<jbyteArray, jbyte, mirror::ByteArray>(env, array, start, length, buf); } static void SetCharArrayRegion(JNIEnv* env, jcharArray array, jsize start, jsize length, const jchar* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(soa, array, start, length, buf); + SetPrimitiveArrayRegion<jcharArray, jchar, mirror::CharArray>(env, array, start, length, buf); } static void SetDoubleArrayRegion(JNIEnv* env, jdoubleArray array, jsize start, jsize length, const jdouble* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(soa, array, start, length, + SetPrimitiveArrayRegion<jdoubleArray, jdouble, mirror::DoubleArray>(env, array, start, length, buf); } static void SetFloatArrayRegion(JNIEnv* env, jfloatArray array, jsize start, jsize length, const jfloat* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(soa, array, start, length, + SetPrimitiveArrayRegion<jfloatArray, jfloat, mirror::FloatArray>(env, array, start, length, buf); } static void SetIntArrayRegion(JNIEnv* env, jintArray array, jsize start, jsize length, const jint* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(soa, array, start, length, buf); + SetPrimitiveArrayRegion<jintArray, jint, mirror::IntArray>(env, array, start, length, buf); } static void SetLongArrayRegion(JNIEnv* env, jlongArray array, jsize start, jsize length, const jlong* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(soa, array, start, length, buf); + SetPrimitiveArrayRegion<jlongArray, jlong, mirror::LongArray>(env, array, start, length, buf); } static void SetShortArrayRegion(JNIEnv* env, jshortArray array, jsize start, jsize length, const jshort* buf) { - ScopedObjectAccess soa(env); - SetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(soa, array, start, length, + SetPrimitiveArrayRegion<jshortArray, jshort, mirror::ShortArray>(env, array, start, length, buf); } @@ -2300,7 +2288,7 @@ class JNI { JniAbortF("RegisterNatives", "negative method count: %d", method_count); return JNI_ERR; // Not reached. } - CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class); + CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", java_class, JNI_ERR); ScopedObjectAccess soa(env); mirror::Class* c = soa.Decode<mirror::Class*>(java_class); if (UNLIKELY(method_count == 0)) { @@ -2308,7 +2296,7 @@ class JNI { << PrettyDescriptor(c); return JNI_OK; } - CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods); + CHECK_NON_NULL_ARGUMENT_FN_NAME("RegisterNatives", methods, JNI_ERR); for (jint i = 0; i < method_count; ++i) { const char* name = methods[i].name; const char* sig = methods[i].signature; @@ -2345,30 +2333,37 @@ class JNI { } static jint UnregisterNatives(JNIEnv* env, jclass java_class) { - CHECK_NON_NULL_ARGUMENT(java_class); + CHECK_NON_NULL_ARGUMENT_RETURN(java_class, JNI_ERR); ScopedObjectAccess soa(env); mirror::Class* c = soa.Decode<mirror::Class*>(java_class); VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]"; + size_t unregistered_count = 0; for (size_t i = 0; i < c->NumDirectMethods(); ++i) { mirror::ArtMethod* m = c->GetDirectMethod(i); if (m->IsNative()) { m->UnregisterNative(soa.Self()); + unregistered_count++; } } for (size_t i = 0; i < c->NumVirtualMethods(); ++i) { mirror::ArtMethod* m = c->GetVirtualMethod(i); if (m->IsNative()) { m->UnregisterNative(soa.Self()); + unregistered_count++; } } + if (unregistered_count == 0) { + LOG(WARNING) << "JNI UnregisterNatives: attempt to unregister native methods of class '" + << PrettyDescriptor(c) << "' that contains no native methods"; + } return JNI_OK; } static jint MonitorEnter(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS { - CHECK_NON_NULL_ARGUMENT(java_object); + CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR); ScopedObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_object); o = o->MonitorEnter(soa.Self()); @@ -2380,7 +2375,7 @@ class JNI { } static jint MonitorExit(JNIEnv* env, jobject java_object) NO_THREAD_SAFETY_ANALYSIS { - CHECK_NON_NULL_ARGUMENT(java_object); + CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNI_ERR); ScopedObjectAccess soa(env); mirror::Object* o = soa.Decode<mirror::Object*>(java_object); o->MonitorExit(soa.Self()); @@ -2392,7 +2387,7 @@ class JNI { } static jint GetJavaVM(JNIEnv* env, JavaVM** vm) { - CHECK_NON_NULL_ARGUMENT(vm); + CHECK_NON_NULL_ARGUMENT_RETURN(vm, JNI_ERR); Runtime* runtime = Runtime::Current(); if (runtime != nullptr) { *vm = runtime->GetJavaVM(); @@ -2432,7 +2427,7 @@ class JNI { } static jobjectRefType GetObjectRefType(JNIEnv* env, jobject java_object) { - CHECK_NON_NULL_ARGUMENT(java_object); + CHECK_NON_NULL_ARGUMENT_RETURN(java_object, JNIInvalidRefType); // Do we definitely know what kind of reference this is? IndirectRef ref = reinterpret_cast<IndirectRef>(java_object); @@ -2479,51 +2474,82 @@ class JNI { } template<typename JniT, typename ArtT> - static JniT NewPrimitiveArray(const ScopedObjectAccess& soa, jsize length) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { + static JniT NewPrimitiveArray(JNIEnv* env, jsize length) { if (UNLIKELY(length < 0)) { JniAbortF("NewPrimitiveArray", "negative array length: %d", length); return nullptr; } + ScopedObjectAccess soa(env); ArtT* result = ArtT::Alloc(soa.Self(), length); return soa.AddLocalReference<JniT>(result); } - template <typename ArrayT, typename CArrayT, typename ArtArrayT> - static CArrayT GetPrimitiveArray(ScopedObjectAccess& soa, ArrayT java_array, - jboolean* is_copy) + template <typename JArrayT, typename ElementT, typename ArtArrayT> + static ArtArrayT* DecodeAndCheckArrayType(ScopedObjectAccess& soa, JArrayT java_array, + const char* fn_name, const char* operation) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { ArtArrayT* array = soa.Decode<ArtArrayT*>(java_array); + if (UNLIKELY(ArtArrayT::GetArrayClass() != array->GetClass())) { + JniAbortF(fn_name, "attempt to %s %s primitive array elements with an object of type %s", + operation, PrettyDescriptor(ArtArrayT::GetArrayClass()->GetComponentType()).c_str(), + PrettyDescriptor(array->GetClass()).c_str()); + return nullptr; + } + DCHECK_EQ(sizeof(ElementT), array->GetClass()->GetComponentSize()); + return array; + } + + template <typename ArrayT, typename ElementT, typename ArtArrayT> + static ElementT* GetPrimitiveArray(JNIEnv* env, ArrayT java_array, jboolean* is_copy) { + CHECK_NON_NULL_ARGUMENT(java_array); + ScopedObjectAccess soa(env); + ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array, + "GetArrayElements", + "get"); + if (UNLIKELY(array == nullptr)) { + return nullptr; + } PinPrimitiveArray(soa, array); // Only make a copy if necessary. if (Runtime::Current()->GetHeap()->IsMovableObject(array)) { if (is_copy != nullptr) { *is_copy = JNI_TRUE; } - static const size_t component_size = array->GetClass()->GetComponentSize(); + const size_t component_size = sizeof(ElementT); size_t size = array->GetLength() * component_size; void* data = new uint64_t[RoundUp(size, 8) / 8]; memcpy(data, array->GetData(), size); - return reinterpret_cast<CArrayT>(data); + return reinterpret_cast<ElementT*>(data); } else { if (is_copy != nullptr) { *is_copy = JNI_FALSE; } - return reinterpret_cast<CArrayT>(array->GetData()); + return reinterpret_cast<ElementT*>(array->GetData()); } } - template <typename ArrayT, typename ElementT> + template <typename ArrayT, typename ElementT, typename ArtArrayT> static void ReleasePrimitiveArray(JNIEnv* env, ArrayT java_array, ElementT* elements, jint mode) { + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array); ScopedObjectAccess soa(env); - mirror::Array* array = soa.Decode<mirror::Array*>(java_array); - size_t component_size = array->GetClass()->GetComponentSize(); + ArtArrayT* array = DecodeAndCheckArrayType<ArrayT, ElementT, ArtArrayT>(soa, java_array, + "ReleaseArrayElements", + "release"); + if (array == nullptr) { + return; + } + ReleasePrimitiveArray(soa, array, sizeof(ElementT), elements, mode); + } + + static void ReleasePrimitiveArray(ScopedObjectAccess& soa, mirror::Array* array, + size_t component_size, void* elements, jint mode) + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { void* array_data = array->GetRawData(component_size, 0); gc::Heap* heap = Runtime::Current()->GetHeap(); - bool is_copy = array_data != reinterpret_cast<void*>(elements); + bool is_copy = array_data != elements; size_t bytes = array->GetLength() * component_size; - VLOG(heap) << "Release primitive array " << env << " array_data " << array_data - << " elements " << reinterpret_cast<void*>(elements); + VLOG(heap) << "Release primitive array " << soa.Env() << " array_data " << array_data + << " elements " << elements; if (is_copy) { // Sanity check: If elements is not the same as the java array's data, it better not be a // heap address. TODO: This might be slow to check, may be worth keeping track of which @@ -2549,33 +2575,43 @@ class JNI { } } - template <typename JavaArrayT, typename JavaT, typename ArrayT> - static void GetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array, - jsize start, jsize length, JavaT* buf) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK_NON_NULL_ARGUMENT(java_array); - ArrayT* array = soa.Decode<ArrayT*>(java_array); - if (start < 0 || length < 0 || start + length > array->GetLength()) { - ThrowAIOOBE(soa, array, start, length, "src"); - } else { - CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf); - JavaT* data = array->GetData(); - memcpy(buf, data + start, length * sizeof(JavaT)); + template <typename JArrayT, typename ElementT, typename ArtArrayT> + static void GetPrimitiveArrayRegion(JNIEnv* env, JArrayT java_array, + jsize start, jsize length, ElementT* buf) { + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array); + ScopedObjectAccess soa(env); + ArtArrayT* array = + DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array, + "GetPrimitiveArrayRegion", + "get region of"); + if (array != nullptr) { + if (start < 0 || length < 0 || start + length > array->GetLength()) { + ThrowAIOOBE(soa, array, start, length, "src"); + } else { + CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf); + ElementT* data = array->GetData(); + memcpy(buf, data + start, length * sizeof(ElementT)); + } } } - template <typename JavaArrayT, typename JavaT, typename ArrayT> - static void SetPrimitiveArrayRegion(ScopedObjectAccess& soa, JavaArrayT java_array, - jsize start, jsize length, const JavaT* buf) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - CHECK_NON_NULL_ARGUMENT(java_array); - ArrayT* array = soa.Decode<ArrayT*>(java_array); - if (start < 0 || length < 0 || start + length > array->GetLength()) { - ThrowAIOOBE(soa, array, start, length, "dst"); - } else { - CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf); - JavaT* data = array->GetData(); - memcpy(data + start, buf, length * sizeof(JavaT)); + template <typename JArrayT, typename ElementT, typename ArtArrayT> + static void SetPrimitiveArrayRegion(JNIEnv* env, JArrayT java_array, + jsize start, jsize length, const ElementT* buf) { + CHECK_NON_NULL_ARGUMENT_RETURN_VOID(java_array); + ScopedObjectAccess soa(env); + ArtArrayT* array = + DecodeAndCheckArrayType<JArrayT, ElementT, ArtArrayT>(soa, java_array, + "SetPrimitiveArrayRegion", + "set region of"); + if (array != nullptr) { + if (start < 0 || length < 0 || start + length > array->GetLength()) { + ThrowAIOOBE(soa, array, start, length, "dst"); + } else { + CHECK_NON_NULL_MEMCPY_ARGUMENT(length, buf); + ElementT* data = array->GetData(); + memcpy(data + start, buf, length * sizeof(ElementT)); + } } } }; diff --git a/runtime/jni_internal_test.cc b/runtime/jni_internal_test.cc index 778b9e5a67..83e9b1028a 100644 --- a/runtime/jni_internal_test.cc +++ b/runtime/jni_internal_test.cc @@ -33,35 +33,54 @@ class JniInternalTest : public CommonCompilerTest { // Turn on -verbose:jni for the JNI tests. // gLogVerbosity.jni = true; - vm_->AttachCurrentThread(&env_, NULL); + vm_->AttachCurrentThread(&env_, nullptr); ScopedLocalRef<jclass> aioobe(env_, env_->FindClass("java/lang/ArrayIndexOutOfBoundsException")); - CHECK(aioobe.get() != NULL); + CHECK(aioobe.get() != nullptr); aioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(aioobe.get())); ScopedLocalRef<jclass> ase(env_, env_->FindClass("java/lang/ArrayStoreException")); - CHECK(ase.get() != NULL); + CHECK(ase.get() != nullptr); ase_ = reinterpret_cast<jclass>(env_->NewGlobalRef(ase.get())); ScopedLocalRef<jclass> sioobe(env_, env_->FindClass("java/lang/StringIndexOutOfBoundsException")); - CHECK(sioobe.get() != NULL); + CHECK(sioobe.get() != nullptr); sioobe_ = reinterpret_cast<jclass>(env_->NewGlobalRef(sioobe.get())); } + void ExpectException(jclass exception_class) { + EXPECT_TRUE(env_->ExceptionCheck()); + jthrowable exception = env_->ExceptionOccurred(); + EXPECT_NE(nullptr, exception); + env_->ExceptionClear(); + EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); + } + + void ExpectClassFound(const char* name) { + EXPECT_NE(env_->FindClass(name), nullptr) << name; + EXPECT_FALSE(env_->ExceptionCheck()) << name; + } + + void ExpectClassNotFound(const char* name) { + EXPECT_EQ(env_->FindClass(name), nullptr) << name; + EXPECT_TRUE(env_->ExceptionCheck()) << name; + env_->ExceptionClear(); + } + void CleanUpJniEnv() { - if (aioobe_ != NULL) { + if (aioobe_ != nullptr) { env_->DeleteGlobalRef(aioobe_); - aioobe_ = NULL; + aioobe_ = nullptr; } - if (ase_ != NULL) { + if (ase_ != nullptr) { env_->DeleteGlobalRef(ase_); - ase_ = NULL; + ase_ = nullptr; } - if (sioobe_ != NULL) { + if (sioobe_ != nullptr) { env_->DeleteGlobalRef(sioobe_); - sioobe_ = NULL; + sioobe_ = nullptr; } } @@ -86,9 +105,9 @@ class JniInternalTest : public CommonCompilerTest { TEST_F(JniInternalTest, AllocObject) { jclass c = env_->FindClass("java/lang/String"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); jobject o = env_->AllocObject(c); - ASSERT_TRUE(o != NULL); + ASSERT_NE(o, nullptr); // We have an instance of the class we asked for... ASSERT_TRUE(env_->IsInstanceOf(o, c)); @@ -96,139 +115,152 @@ TEST_F(JniInternalTest, AllocObject) { // we didn't call a constructor. ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "count", "I"))); ASSERT_EQ(0, env_->GetIntField(o, env_->GetFieldID(c, "offset", "I"))); - ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == NULL); + ASSERT_TRUE(env_->GetObjectField(o, env_->GetFieldID(c, "value", "[C")) == nullptr); } TEST_F(JniInternalTest, GetVersion) { ASSERT_EQ(JNI_VERSION_1_6, env_->GetVersion()); } -#define EXPECT_CLASS_FOUND(NAME) \ - EXPECT_TRUE(env_->FindClass(NAME) != NULL); \ - EXPECT_FALSE(env_->ExceptionCheck()) - -#define EXPECT_CLASS_NOT_FOUND(NAME) \ - EXPECT_TRUE(env_->FindClass(NAME) == NULL); \ - EXPECT_TRUE(env_->ExceptionCheck()); \ - env_->ExceptionClear() - TEST_F(JniInternalTest, FindClass) { // Reference types... - EXPECT_CLASS_FOUND("java/lang/String"); + ExpectClassFound("java/lang/String"); // ...for arrays too, where you must include "L;". - EXPECT_CLASS_FOUND("[Ljava/lang/String;"); + ExpectClassFound("[Ljava/lang/String;"); // Primitive arrays are okay too, if the primitive type is valid. - EXPECT_CLASS_FOUND("[C"); + ExpectClassFound("[C"); { - // We support . as well as / for compatibility, if -Xcheck:jni is off. CheckJniAbortCatcher check_jni_abort_catcher; - EXPECT_CLASS_FOUND("java.lang.String"); + env_->FindClass(nullptr); + check_jni_abort_catcher.Check("name == null"); + + // We support . as well as / for compatibility, if -Xcheck:jni is off. + ExpectClassFound("java.lang.String"); check_jni_abort_catcher.Check("illegal class name 'java.lang.String'"); - EXPECT_CLASS_NOT_FOUND("Ljava.lang.String;"); + ExpectClassNotFound("Ljava.lang.String;"); check_jni_abort_catcher.Check("illegal class name 'Ljava.lang.String;'"); - EXPECT_CLASS_FOUND("[Ljava.lang.String;"); + ExpectClassFound("[Ljava.lang.String;"); check_jni_abort_catcher.Check("illegal class name '[Ljava.lang.String;'"); - EXPECT_CLASS_NOT_FOUND("[java.lang.String"); + ExpectClassNotFound("[java.lang.String"); check_jni_abort_catcher.Check("illegal class name '[java.lang.String'"); // You can't include the "L;" in a JNI class descriptor. - EXPECT_CLASS_NOT_FOUND("Ljava/lang/String;"); + ExpectClassNotFound("Ljava/lang/String;"); check_jni_abort_catcher.Check("illegal class name 'Ljava/lang/String;'"); // But you must include it for an array of any reference type. - EXPECT_CLASS_NOT_FOUND("[java/lang/String"); + ExpectClassNotFound("[java/lang/String"); check_jni_abort_catcher.Check("illegal class name '[java/lang/String'"); - EXPECT_CLASS_NOT_FOUND("[K"); + ExpectClassNotFound("[K"); check_jni_abort_catcher.Check("illegal class name '[K'"); + + // Void arrays aren't allowed. + ExpectClassNotFound("[V"); + check_jni_abort_catcher.Check("illegal class name '[V'"); } // But primitive types aren't allowed... - EXPECT_CLASS_NOT_FOUND("C"); - EXPECT_CLASS_NOT_FOUND("K"); + ExpectClassNotFound("C"); + ExpectClassNotFound("V"); + ExpectClassNotFound("K"); } -#define EXPECT_EXCEPTION(exception_class) \ - do { \ - EXPECT_TRUE(env_->ExceptionCheck()); \ - jthrowable exception = env_->ExceptionOccurred(); \ - EXPECT_NE(static_cast<jthrowable>(NULL), exception); \ - env_->ExceptionClear(); \ - EXPECT_TRUE(env_->IsInstanceOf(exception, exception_class)); \ - } while (false) - TEST_F(JniInternalTest, GetFieldID) { jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError"); - ASSERT_TRUE(jlnsfe != NULL); + ASSERT_NE(jlnsfe, nullptr); jclass c = env_->FindClass("java/lang/String"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); // Wrong type. jfieldID fid = env_->GetFieldID(c, "count", "J"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); // Wrong type where type doesn't exist. fid = env_->GetFieldID(c, "count", "Lrod/jane/freddy;"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); // Wrong name. fid = env_->GetFieldID(c, "Count", "I"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); // Good declared field lookup. fid = env_->GetFieldID(c, "count", "I"); - EXPECT_NE(static_cast<jfieldID>(NULL), fid); - EXPECT_TRUE(fid != NULL); + EXPECT_NE(nullptr, fid); EXPECT_FALSE(env_->ExceptionCheck()); // Good superclass field lookup. c = env_->FindClass("java/lang/StringBuilder"); fid = env_->GetFieldID(c, "count", "I"); - EXPECT_NE(static_cast<jfieldID>(NULL), fid); - EXPECT_TRUE(fid != NULL); + EXPECT_NE(nullptr, fid); + EXPECT_NE(fid, nullptr); EXPECT_FALSE(env_->ExceptionCheck()); // Not instance. fid = env_->GetFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); + + // Bad arguments. + CheckJniAbortCatcher check_jni_abort_catcher; + fid = env_->GetFieldID(nullptr, "count", "I"); + EXPECT_EQ(nullptr, fid); + check_jni_abort_catcher.Check("java_class == null"); + fid = env_->GetFieldID(c, nullptr, "I"); + EXPECT_EQ(nullptr, fid); + check_jni_abort_catcher.Check("name == null"); + fid = env_->GetFieldID(c, "count", nullptr); + EXPECT_EQ(nullptr, fid); + check_jni_abort_catcher.Check("sig == null"); } TEST_F(JniInternalTest, GetStaticFieldID) { jclass jlnsfe = env_->FindClass("java/lang/NoSuchFieldError"); - ASSERT_TRUE(jlnsfe != NULL); + ASSERT_NE(jlnsfe, nullptr); jclass c = env_->FindClass("java/lang/String"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); // Wrong type. jfieldID fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "J"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); // Wrong type where type doesn't exist. fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Lrod/jane/freddy;"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); // Wrong name. fid = env_->GetStaticFieldID(c, "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); // Good declared field lookup. fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); - EXPECT_NE(static_cast<jfieldID>(NULL), fid); - EXPECT_TRUE(fid != NULL); + EXPECT_NE(nullptr, fid); + EXPECT_NE(fid, nullptr); EXPECT_FALSE(env_->ExceptionCheck()); // Not static. fid = env_->GetStaticFieldID(c, "count", "I"); - EXPECT_EQ(static_cast<jfieldID>(NULL), fid); - EXPECT_EXCEPTION(jlnsfe); + EXPECT_EQ(nullptr, fid); + ExpectException(jlnsfe); + + // Bad arguments. + CheckJniAbortCatcher check_jni_abort_catcher; + fid = env_->GetStaticFieldID(nullptr, "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;"); + EXPECT_EQ(nullptr, fid); + check_jni_abort_catcher.Check("java_class == null"); + fid = env_->GetStaticFieldID(c, nullptr, "Ljava/util/Comparator;"); + EXPECT_EQ(nullptr, fid); + check_jni_abort_catcher.Check("name == null"); + fid = env_->GetStaticFieldID(c, "CASE_INSENSITIVE_ORDER", nullptr); + EXPECT_EQ(nullptr, fid); + check_jni_abort_catcher.Check("sig == null"); } TEST_F(JniInternalTest, GetMethodID) { @@ -242,24 +274,36 @@ TEST_F(JniInternalTest, GetMethodID) { // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is // a pending exception jmethodID method = env_->GetMethodID(jlobject, "foo", "()V"); - EXPECT_EQ(static_cast<jmethodID>(NULL), method); - EXPECT_EXCEPTION(jlnsme); + EXPECT_EQ(nullptr, method); + ExpectException(jlnsme); // Check that java.lang.Object.equals() does exist method = env_->GetMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z"); - EXPECT_NE(static_cast<jmethodID>(NULL), method); + EXPECT_NE(nullptr, method); EXPECT_FALSE(env_->ExceptionCheck()); // Check that GetMethodID for java.lang.String.valueOf(int) fails as the // method is static method = env_->GetMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;"); - EXPECT_EQ(static_cast<jmethodID>(NULL), method); - EXPECT_EXCEPTION(jlnsme); + EXPECT_EQ(nullptr, method); + ExpectException(jlnsme); // Check that GetMethodID for java.lang.NoSuchMethodError.<init>(String) finds the constructor method = env_->GetMethodID(jlnsme, "<init>", "(Ljava/lang/String;)V"); - EXPECT_NE(static_cast<jmethodID>(NULL), method); + EXPECT_NE(nullptr, method); EXPECT_FALSE(env_->ExceptionCheck()); + + // Bad arguments. + CheckJniAbortCatcher check_jni_abort_catcher; + method = env_->GetMethodID(nullptr, "<init>", "(Ljava/lang/String;)V"); + EXPECT_EQ(nullptr, method); + check_jni_abort_catcher.Check("java_class == null"); + method = env_->GetMethodID(jlnsme, nullptr, "(Ljava/lang/String;)V"); + EXPECT_EQ(nullptr, method); + check_jni_abort_catcher.Check("name == null"); + method = env_->GetMethodID(jlnsme, "<init>", nullptr); + EXPECT_EQ(nullptr, method); + check_jni_abort_catcher.Check("sig == null"); } TEST_F(JniInternalTest, GetStaticMethodID) { @@ -272,93 +316,155 @@ TEST_F(JniInternalTest, GetStaticMethodID) { // Check that java.lang.Object.foo() doesn't exist and NoSuchMethodError is // a pending exception jmethodID method = env_->GetStaticMethodID(jlobject, "foo", "()V"); - EXPECT_EQ(static_cast<jmethodID>(NULL), method); - EXPECT_EXCEPTION(jlnsme); + EXPECT_EQ(nullptr, method); + ExpectException(jlnsme); // Check that GetStaticMethodID for java.lang.Object.equals(Object) fails as // the method is not static method = env_->GetStaticMethodID(jlobject, "equals", "(Ljava/lang/Object;)Z"); - EXPECT_EQ(static_cast<jmethodID>(NULL), method); - EXPECT_EXCEPTION(jlnsme); + EXPECT_EQ(nullptr, method); + ExpectException(jlnsme); // Check that java.lang.String.valueOf(int) does exist jclass jlstring = env_->FindClass("java/lang/String"); - method = env_->GetStaticMethodID(jlstring, "valueOf", - "(I)Ljava/lang/String;"); - EXPECT_NE(static_cast<jmethodID>(NULL), method); + method = env_->GetStaticMethodID(jlstring, "valueOf", "(I)Ljava/lang/String;"); + EXPECT_NE(nullptr, method); EXPECT_FALSE(env_->ExceptionCheck()); + + // Bad arguments. + CheckJniAbortCatcher check_jni_abort_catcher; + method = env_->GetStaticMethodID(nullptr, "valueOf", "(I)Ljava/lang/String;"); + EXPECT_EQ(nullptr, method); + check_jni_abort_catcher.Check("java_class == null"); + method = env_->GetStaticMethodID(jlstring, nullptr, "(I)Ljava/lang/String;"); + EXPECT_EQ(nullptr, method); + check_jni_abort_catcher.Check("name == null"); + method = env_->GetStaticMethodID(jlstring, "valueOf", nullptr); + EXPECT_EQ(nullptr, method); + check_jni_abort_catcher.Check("sig == null"); } TEST_F(JniInternalTest, FromReflectedField_ToReflectedField) { jclass jlrField = env_->FindClass("java/lang/reflect/Field"); jclass c = env_->FindClass("java/lang/String"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); jfieldID fid = env_->GetFieldID(c, "count", "I"); - ASSERT_TRUE(fid != NULL); + ASSERT_NE(fid, nullptr); // Turn the fid into a java.lang.reflect.Field... jobject field = env_->ToReflectedField(c, fid, JNI_FALSE); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); ASSERT_TRUE(env_->IsInstanceOf(field, jlrField)); // ...and back again. jfieldID fid2 = env_->FromReflectedField(field); - ASSERT_TRUE(fid2 != NULL); + ASSERT_NE(fid2, nullptr); // Make sure we can actually use it. jstring s = env_->NewStringUTF("poop"); ASSERT_EQ(4, env_->GetIntField(s, fid2)); + + // Bad arguments. + CheckJniAbortCatcher check_jni_abort_catcher; + field = env_->ToReflectedField(c, nullptr, JNI_FALSE); + EXPECT_EQ(field, nullptr); + check_jni_abort_catcher.Check("fid == null"); + fid2 = env_->FromReflectedField(nullptr); + ASSERT_EQ(fid2, nullptr); + check_jni_abort_catcher.Check("jlr_field == null"); } TEST_F(JniInternalTest, FromReflectedMethod_ToReflectedMethod) { jclass jlrMethod = env_->FindClass("java/lang/reflect/Method"); jclass c = env_->FindClass("java/lang/String"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); jmethodID mid = env_->GetMethodID(c, "length", "()I"); - ASSERT_TRUE(mid != NULL); + ASSERT_NE(mid, nullptr); // Turn the mid into a java.lang.reflect.Method... jobject method = env_->ToReflectedMethod(c, mid, JNI_FALSE); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); ASSERT_TRUE(env_->IsInstanceOf(method, jlrMethod)); // ...and back again. jmethodID mid2 = env_->FromReflectedMethod(method); - ASSERT_TRUE(mid2 != NULL); + ASSERT_NE(mid2, nullptr); // Make sure we can actually use it. jstring s = env_->NewStringUTF("poop"); ASSERT_EQ(4, env_->CallIntMethod(s, mid2)); + + // Bad arguments. + CheckJniAbortCatcher check_jni_abort_catcher; + method = env_->ToReflectedMethod(c, nullptr, JNI_FALSE); + EXPECT_EQ(method, nullptr); + check_jni_abort_catcher.Check("mid == null"); + mid2 = env_->FromReflectedMethod(method); + ASSERT_EQ(mid2, nullptr); + check_jni_abort_catcher.Check("jlr_method == null"); } -void BogusMethod() { - // You can't pass NULL function pointers to RegisterNatives. +static void BogusMethod() { + // You can't pass nullptr function pointers to RegisterNatives. } -TEST_F(JniInternalTest, RegisterNatives) { +TEST_F(JniInternalTest, RegisterAndUnregisterNatives) { jclass jlobject = env_->FindClass("java/lang/Object"); jclass jlnsme = env_->FindClass("java/lang/NoSuchMethodError"); - // Sanity check that no exceptions are pending + // Sanity check that no exceptions are pending. ASSERT_FALSE(env_->ExceptionCheck()); - // Check that registering to a non-existent java.lang.Object.foo() causes a - // NoSuchMethodError + // Check that registering to a non-existent java.lang.Object.foo() causes a NoSuchMethodError. { - JNINativeMethod methods[] = { { "foo", "()V", NULL } }; - env_->RegisterNatives(jlobject, methods, 1); + JNINativeMethod methods[] = { { "foo", "()V", nullptr } }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); } - EXPECT_EXCEPTION(jlnsme); + ExpectException(jlnsme); - // Check that registering non-native methods causes a NoSuchMethodError + // Check that registering non-native methods causes a NoSuchMethodError. { - JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", NULL } }; - env_->RegisterNatives(jlobject, methods, 1); + JNINativeMethod methods[] = { { "equals", "(Ljava/lang/Object;)Z", nullptr } }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_ERR); } - EXPECT_EXCEPTION(jlnsme); + ExpectException(jlnsme); - // Check that registering native methods is successful + // Check that registering native methods is successful. { JNINativeMethod methods[] = { { "notify", "()V", reinterpret_cast<void*>(BogusMethod) } }; - env_->RegisterNatives(jlobject, methods, 1); + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 1), JNI_OK); + } + EXPECT_FALSE(env_->ExceptionCheck()); + EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK); + + // Check that registering no methods isn't a failure. + { + JNINativeMethod methods[] = { }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, 0), JNI_OK); + } + EXPECT_FALSE(env_->ExceptionCheck()); + EXPECT_EQ(env_->UnregisterNatives(jlobject), JNI_OK); + + // Check that registering a -ve number of methods is a failure. + CheckJniAbortCatcher check_jni_abort_catcher; + for (int i = -10; i < 0; ++i) { + JNINativeMethod methods[] = { }; + EXPECT_EQ(env_->RegisterNatives(jlobject, methods, i), JNI_ERR); + check_jni_abort_catcher.Check("negative method count: "); } EXPECT_FALSE(env_->ExceptionCheck()); - env_->UnregisterNatives(jlobject); + // Passing a class of null is a failure. + { + JNINativeMethod methods[] = { }; + EXPECT_EQ(env_->RegisterNatives(nullptr, methods, 0), JNI_ERR); + check_jni_abort_catcher.Check("java_class == null"); + } + + // Passing methods as null is a failure. + EXPECT_EQ(env_->RegisterNatives(jlobject, nullptr, 1), JNI_ERR); + check_jni_abort_catcher.Check("methods == null"); + + // Unregisters null is a failure. + EXPECT_EQ(env_->UnregisterNatives(nullptr), JNI_ERR); + check_jni_abort_catcher.Check("java_class == null"); + + // Unregistering a class with no natives is a warning. + EXPECT_EQ(env_->UnregisterNatives(jlnsme), JNI_OK); } #define EXPECT_PRIMITIVE_ARRAY(new_fn, \ @@ -368,52 +474,69 @@ TEST_F(JniInternalTest, RegisterNatives) { release_elements_fn, \ scalar_type, \ expected_class_descriptor) \ + jsize size = 4; \ + \ { \ CheckJniAbortCatcher jni_abort_catcher; \ /* Allocate an negative sized array and check it has the right failure type. */ \ - env_->new_fn(-1); \ + EXPECT_EQ(env_->new_fn(-1), nullptr); \ jni_abort_catcher.Check("negative array length: -1"); \ - env_->new_fn(std::numeric_limits<jint>::min()); \ + EXPECT_EQ(env_->new_fn(std::numeric_limits<jint>::min()), nullptr); \ jni_abort_catcher.Check("negative array length: -2147483648"); \ + /* Pass the array as null. */ \ + EXPECT_EQ(0, env_->GetArrayLength(nullptr)); \ + jni_abort_catcher.Check("java_array == null"); \ + env_->get_region_fn(nullptr, 0, 0, nullptr); \ + jni_abort_catcher.Check("java_array == null"); \ + env_->set_region_fn(nullptr, 0, 0, nullptr); \ + jni_abort_catcher.Check("java_array == null"); \ + env_->get_elements_fn(nullptr, nullptr); \ + jni_abort_catcher.Check("java_array == null"); \ + env_->release_elements_fn(nullptr, nullptr, 0); \ + jni_abort_catcher.Check("java_array == null"); \ + /* Pass the elements for region as null. */ \ + scalar_type ## Array a = env_->new_fn(size); \ + env_->get_region_fn(a, 0, size, nullptr); \ + jni_abort_catcher.Check("buf == null"); \ + env_->set_region_fn(a, 0, size, nullptr); \ + jni_abort_catcher.Check("buf == null"); \ } \ - jsize size = 4; \ - \ /* Allocate an array and check it has the right type and length. */ \ scalar_type ## Array a = env_->new_fn(size); \ - EXPECT_TRUE(a != NULL); \ + EXPECT_NE(a, nullptr); \ EXPECT_TRUE(env_->IsInstanceOf(a, env_->FindClass(expected_class_descriptor))); \ EXPECT_EQ(size, env_->GetArrayLength(a)); \ \ /* GetPrimitiveArrayRegion/SetPrimitiveArrayRegion */ \ /* AIOOBE for negative start offset. */ \ - env_->get_region_fn(a, -1, 1, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ - env_->set_region_fn(a, -1, 1, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ + env_->get_region_fn(a, -1, 1, nullptr); \ + ExpectException(aioobe_); \ + env_->set_region_fn(a, -1, 1, nullptr); \ + ExpectException(aioobe_); \ \ /* AIOOBE for negative length. */ \ - env_->get_region_fn(a, 0, -1, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ - env_->set_region_fn(a, 0, -1, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ + env_->get_region_fn(a, 0, -1, nullptr); \ + ExpectException(aioobe_); \ + env_->set_region_fn(a, 0, -1, nullptr); \ + ExpectException(aioobe_); \ \ /* AIOOBE for buffer overrun. */ \ - env_->get_region_fn(a, size - 1, size, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ - env_->set_region_fn(a, size - 1, size, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ + env_->get_region_fn(a, size - 1, size, nullptr); \ + ExpectException(aioobe_); \ + env_->set_region_fn(a, size - 1, size, nullptr); \ + ExpectException(aioobe_); \ \ - /* It's okay for the buffer to be NULL as long as the length is 0. */ \ - env_->get_region_fn(a, 2, 0, NULL); \ + /* It's okay for the buffer to be nullptr as long as the length is 0. */ \ + env_->get_region_fn(a, 2, 0, nullptr); \ /* Even if the offset is invalid... */ \ - env_->get_region_fn(a, 123, 0, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ + env_->get_region_fn(a, 123, 0, nullptr); \ + ExpectException(aioobe_); \ \ - /* It's okay for the buffer to be NULL as long as the length is 0. */ \ - env_->set_region_fn(a, 2, 0, NULL); \ + /* It's okay for the buffer to be nullptr as long as the length is 0. */ \ + env_->set_region_fn(a, 2, 0, nullptr); \ /* Even if the offset is invalid... */ \ - env_->set_region_fn(a, 123, 0, NULL); \ - EXPECT_EXCEPTION(aioobe_); \ + env_->set_region_fn(a, 123, 0, nullptr); \ + ExpectException(aioobe_); \ \ /* Prepare a couple of buffers. */ \ UniquePtr<scalar_type[]> src_buf(new scalar_type[size]); \ @@ -437,12 +560,12 @@ TEST_F(JniInternalTest, RegisterNatives) { EXPECT_EQ(memcmp(&src_buf[0], &dst_buf[0], size * sizeof(scalar_type)), 0) \ << "full copy not equal"; \ /* GetPrimitiveArrayCritical */ \ - void* v = env_->GetPrimitiveArrayCritical(a, NULL); \ + void* v = env_->GetPrimitiveArrayCritical(a, nullptr); \ EXPECT_EQ(memcmp(&src_buf[0], v, size * sizeof(scalar_type)), 0) \ << "GetPrimitiveArrayCritical not equal"; \ env_->ReleasePrimitiveArrayCritical(a, v, 0); \ /* GetXArrayElements */ \ - scalar_type* xs = env_->get_elements_fn(a, NULL); \ + scalar_type* xs = env_->get_elements_fn(a, nullptr); \ EXPECT_EQ(memcmp(&src_buf[0], xs, size * sizeof(scalar_type)), 0) \ << # get_elements_fn " not equal"; \ env_->release_elements_fn(a, xs, 0); \ @@ -480,31 +603,206 @@ TEST_F(JniInternalTest, ShortArrays) { GetShortArrayElements, ReleaseShortArrayElements, jshort, "[S"); } +TEST_F(JniInternalTest, GetPrimitiveArrayElementsOfWrongType) { + CheckJniAbortCatcher jni_abort_catcher; + jbooleanArray array = env_->NewBooleanArray(10); + jboolean is_copy; + EXPECT_EQ(env_->GetByteArrayElements(reinterpret_cast<jbyteArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get byte primitive array elements with an object of type boolean[]"); + EXPECT_EQ(env_->GetShortArrayElements(reinterpret_cast<jshortArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get short primitive array elements with an object of type boolean[]"); + EXPECT_EQ(env_->GetCharArrayElements(reinterpret_cast<jcharArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get char primitive array elements with an object of type boolean[]"); + EXPECT_EQ(env_->GetIntArrayElements(reinterpret_cast<jintArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get int primitive array elements with an object of type boolean[]"); + EXPECT_EQ(env_->GetLongArrayElements(reinterpret_cast<jlongArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get long primitive array elements with an object of type boolean[]"); + EXPECT_EQ(env_->GetFloatArrayElements(reinterpret_cast<jfloatArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get float primitive array elements with an object of type boolean[]"); + EXPECT_EQ(env_->GetDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get double primitive array elements with an object of type boolean[]"); + jbyteArray array2 = env_->NewByteArray(10); + EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get boolean primitive array elements with an object of type byte[]"); + jobject object = env_->NewStringUTF("Test String"); + EXPECT_EQ(env_->GetBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), &is_copy), nullptr); + jni_abort_catcher.Check( + "attempt to get boolean primitive array elements with an object of type java.lang.String"); +} + +TEST_F(JniInternalTest, ReleasePrimitiveArrayElementsOfWrongType) { + CheckJniAbortCatcher jni_abort_catcher; + jbooleanArray array = env_->NewBooleanArray(10); + ASSERT_TRUE(array != nullptr); + jboolean is_copy; + jboolean* elements = env_->GetBooleanArrayElements(array, &is_copy); + ASSERT_TRUE(elements != nullptr); + env_->ReleaseByteArrayElements(reinterpret_cast<jbyteArray>(array), + reinterpret_cast<jbyte*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release byte primitive array elements with an object of type boolean[]"); + env_->ReleaseShortArrayElements(reinterpret_cast<jshortArray>(array), + reinterpret_cast<jshort*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release short primitive array elements with an object of type boolean[]"); + env_->ReleaseCharArrayElements(reinterpret_cast<jcharArray>(array), + reinterpret_cast<jchar*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release char primitive array elements with an object of type boolean[]"); + env_->ReleaseIntArrayElements(reinterpret_cast<jintArray>(array), + reinterpret_cast<jint*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release int primitive array elements with an object of type boolean[]"); + env_->ReleaseLongArrayElements(reinterpret_cast<jlongArray>(array), + reinterpret_cast<jlong*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release long primitive array elements with an object of type boolean[]"); + env_->ReleaseFloatArrayElements(reinterpret_cast<jfloatArray>(array), + reinterpret_cast<jfloat*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release float primitive array elements with an object of type boolean[]"); + env_->ReleaseDoubleArrayElements(reinterpret_cast<jdoubleArray>(array), + reinterpret_cast<jdouble*>(elements), 0); + jni_abort_catcher.Check( + "attempt to release double primitive array elements with an object of type boolean[]"); + jbyteArray array2 = env_->NewByteArray(10); + env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(array2), elements, 0); + jni_abort_catcher.Check( + "attempt to release boolean primitive array elements with an object of type byte[]"); + jobject object = env_->NewStringUTF("Test String"); + env_->ReleaseBooleanArrayElements(reinterpret_cast<jbooleanArray>(object), elements, 0); + jni_abort_catcher.Check( + "attempt to release boolean primitive array elements with an object of type java.lang.String"); +} +TEST_F(JniInternalTest, GetReleasePrimitiveArrayCriticalOfWrongType) { + CheckJniAbortCatcher jni_abort_catcher; + jobject object = env_->NewStringUTF("Test String"); + jboolean is_copy; + void* elements = env_->GetPrimitiveArrayCritical(reinterpret_cast<jarray>(object), &is_copy); + jni_abort_catcher.Check("expected primitive array, given java.lang.String"); + env_->ReleasePrimitiveArrayCritical(reinterpret_cast<jarray>(object), elements, 0); + jni_abort_catcher.Check("expected primitive array, given java.lang.String"); +} + +TEST_F(JniInternalTest, GetPrimitiveArrayRegionElementsOfWrongType) { + CheckJniAbortCatcher jni_abort_catcher; + constexpr size_t kLength = 10; + jbooleanArray array = env_->NewBooleanArray(kLength); + ASSERT_TRUE(array != nullptr); + jboolean elements[kLength]; + env_->GetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength, + reinterpret_cast<jbyte*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of byte primitive array elements with an object of type boolean[]"); + env_->GetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength, + reinterpret_cast<jshort*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of short primitive array elements with an object of type boolean[]"); + env_->GetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength, + reinterpret_cast<jchar*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of char primitive array elements with an object of type boolean[]"); + env_->GetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength, + reinterpret_cast<jint*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of int primitive array elements with an object of type boolean[]"); + env_->GetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength, + reinterpret_cast<jlong*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of long primitive array elements with an object of type boolean[]"); + env_->GetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength, + reinterpret_cast<jfloat*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of float primitive array elements with an object of type boolean[]"); + env_->GetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength, + reinterpret_cast<jdouble*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of double primitive array elements with an object of type boolean[]"); + jbyteArray array2 = env_->NewByteArray(10); + env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength, + reinterpret_cast<jboolean*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of boolean primitive array elements with an object of type byte[]"); + jobject object = env_->NewStringUTF("Test String"); + env_->GetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength, + reinterpret_cast<jboolean*>(elements)); + jni_abort_catcher.Check( + "attempt to get region of boolean primitive array elements with an object of type java.lang.String"); +} + +TEST_F(JniInternalTest, SetPrimitiveArrayRegionElementsOfWrongType) { + CheckJniAbortCatcher jni_abort_catcher; + constexpr size_t kLength = 10; + jbooleanArray array = env_->NewBooleanArray(kLength); + ASSERT_TRUE(array != nullptr); + jboolean elements[kLength]; + env_->SetByteArrayRegion(reinterpret_cast<jbyteArray>(array), 0, kLength, + reinterpret_cast<jbyte*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of byte primitive array elements with an object of type boolean[]"); + env_->SetShortArrayRegion(reinterpret_cast<jshortArray>(array), 0, kLength, + reinterpret_cast<jshort*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of short primitive array elements with an object of type boolean[]"); + env_->SetCharArrayRegion(reinterpret_cast<jcharArray>(array), 0, kLength, + reinterpret_cast<jchar*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of char primitive array elements with an object of type boolean[]"); + env_->SetIntArrayRegion(reinterpret_cast<jintArray>(array), 0, kLength, + reinterpret_cast<jint*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of int primitive array elements with an object of type boolean[]"); + env_->SetLongArrayRegion(reinterpret_cast<jlongArray>(array), 0, kLength, + reinterpret_cast<jlong*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of long primitive array elements with an object of type boolean[]"); + env_->SetFloatArrayRegion(reinterpret_cast<jfloatArray>(array), 0, kLength, + reinterpret_cast<jfloat*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of float primitive array elements with an object of type boolean[]"); + env_->SetDoubleArrayRegion(reinterpret_cast<jdoubleArray>(array), 0, kLength, + reinterpret_cast<jdouble*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of double primitive array elements with an object of type boolean[]"); + jbyteArray array2 = env_->NewByteArray(10); + env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(array2), 0, kLength, + reinterpret_cast<jboolean*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of boolean primitive array elements with an object of type byte[]"); + jobject object = env_->NewStringUTF("Test String"); + env_->SetBooleanArrayRegion(reinterpret_cast<jbooleanArray>(object), 0, kLength, + reinterpret_cast<jboolean*>(elements)); + jni_abort_catcher.Check( + "attempt to set region of boolean primitive array elements with an object of type java.lang.String"); +} + TEST_F(JniInternalTest, NewObjectArray) { jclass element_class = env_->FindClass("java/lang/String"); - ASSERT_TRUE(element_class != nullptr); + ASSERT_NE(element_class, nullptr); jclass array_class = env_->FindClass("[Ljava/lang/String;"); - ASSERT_TRUE(array_class != nullptr); + ASSERT_NE(array_class, nullptr); jobjectArray a = env_->NewObjectArray(0, element_class, nullptr); - EXPECT_TRUE(a != nullptr); + EXPECT_NE(a, nullptr); EXPECT_TRUE(env_->IsInstanceOf(a, array_class)); EXPECT_EQ(0, env_->GetArrayLength(a)); a = env_->NewObjectArray(1, element_class, nullptr); - EXPECT_TRUE(a != nullptr); + EXPECT_NE(a, nullptr); EXPECT_TRUE(env_->IsInstanceOf(a, array_class)); EXPECT_EQ(1, env_->GetArrayLength(a)); EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), nullptr)); -} -TEST_F(JniInternalTest, NewObjectArrayWithNegativeLength) { - jclass element_class = env_->FindClass("java/lang/String"); - ASSERT_TRUE(element_class != nullptr); - jclass array_class = env_->FindClass("[Ljava/lang/String;"); - ASSERT_TRUE(array_class != nullptr); + // Negative array length checks. CheckJniAbortCatcher jni_abort_catcher; - env_->NewObjectArray(-1, element_class, nullptr); jni_abort_catcher.Check("negative array length: -1"); @@ -521,6 +819,8 @@ TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) { CheckJniAbortCatcher jni_abort_catcher; for (size_t i = 0; i < strlen(primitive_descriptors); ++i) { + env_->NewObjectArray(0, nullptr, nullptr); + jni_abort_catcher.Check("element_jclass == null"); jclass primitive_class = GetPrimitiveClass(primitive_descriptors[i]); env_->NewObjectArray(1, primitive_class, nullptr); std::string error_msg(StringPrintf("not an object type: %s", primitive_names[i])); @@ -530,13 +830,13 @@ TEST_F(JniInternalTest, NewObjectArrayWithPrimitiveClasses) { TEST_F(JniInternalTest, NewObjectArrayWithInitialValue) { jclass element_class = env_->FindClass("java/lang/String"); - ASSERT_TRUE(element_class != nullptr); + ASSERT_NE(element_class, nullptr); jclass array_class = env_->FindClass("[Ljava/lang/String;"); - ASSERT_TRUE(array_class != nullptr); + ASSERT_NE(array_class, nullptr); jstring s = env_->NewStringUTF("poop"); jobjectArray a = env_->NewObjectArray(2, element_class, s); - EXPECT_TRUE(a != nullptr); + EXPECT_NE(a, nullptr); EXPECT_TRUE(env_->IsInstanceOf(a, array_class)); EXPECT_EQ(2, env_->GetArrayLength(a)); EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(a, 0), s)); @@ -555,9 +855,9 @@ TEST_F(JniInternalTest, GetArrayLength) { TEST_F(JniInternalTest, GetObjectClass) { jclass string_class = env_->FindClass("java/lang/String"); - ASSERT_TRUE(string_class != NULL); + ASSERT_NE(string_class, nullptr); jclass class_class = env_->FindClass("java/lang/Class"); - ASSERT_TRUE(class_class != NULL); + ASSERT_NE(class_class, nullptr); jstring s = env_->NewStringUTF("poop"); jclass c = env_->GetObjectClass(s); @@ -565,33 +865,50 @@ TEST_F(JniInternalTest, GetObjectClass) { jclass c2 = env_->GetObjectClass(c); ASSERT_TRUE(env_->IsSameObject(class_class, env_->GetObjectClass(c2))); + + // Null as object should fail. + CheckJniAbortCatcher jni_abort_catcher; + EXPECT_EQ(env_->GetObjectClass(nullptr), nullptr); + jni_abort_catcher.Check("java_object == null"); } TEST_F(JniInternalTest, GetSuperclass) { jclass object_class = env_->FindClass("java/lang/Object"); - ASSERT_TRUE(object_class != NULL); + ASSERT_NE(object_class, nullptr); jclass string_class = env_->FindClass("java/lang/String"); - ASSERT_TRUE(string_class != NULL); + ASSERT_NE(string_class, nullptr); jclass runnable_interface = env_->FindClass("java/lang/Runnable"); - ASSERT_TRUE(runnable_interface != NULL); + ASSERT_NE(runnable_interface, nullptr); ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(string_class))); - ASSERT_TRUE(env_->GetSuperclass(object_class) == NULL); + ASSERT_EQ(env_->GetSuperclass(object_class), nullptr); ASSERT_TRUE(env_->IsSameObject(object_class, env_->GetSuperclass(runnable_interface))); + + // Null as class should fail. + CheckJniAbortCatcher jni_abort_catcher; + EXPECT_EQ(env_->GetSuperclass(nullptr), nullptr); + jni_abort_catcher.Check("java_class == null"); } TEST_F(JniInternalTest, IsAssignableFrom) { jclass object_class = env_->FindClass("java/lang/Object"); - ASSERT_TRUE(object_class != NULL); + ASSERT_NE(object_class, nullptr); jclass string_class = env_->FindClass("java/lang/String"); - ASSERT_TRUE(string_class != NULL); + ASSERT_NE(string_class, nullptr); ASSERT_TRUE(env_->IsAssignableFrom(object_class, string_class)); ASSERT_FALSE(env_->IsAssignableFrom(string_class, object_class)); + + // Null as either class should fail. + CheckJniAbortCatcher jni_abort_catcher; + EXPECT_EQ(env_->IsAssignableFrom(nullptr, string_class), JNI_FALSE); + jni_abort_catcher.Check("java_class1 == null"); + EXPECT_EQ(env_->IsAssignableFrom(object_class, nullptr), JNI_FALSE); + jni_abort_catcher.Check("java_class2 == null"); } TEST_F(JniInternalTest, GetObjectRefType) { jclass local = env_->FindClass("java/lang/Object"); - ASSERT_TRUE(local != NULL); + ASSERT_TRUE(local != nullptr); EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(local)); jobject global = env_->NewGlobalRef(local); @@ -604,33 +921,38 @@ TEST_F(JniInternalTest, GetObjectRefType) { EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(invalid)); // TODO: invoke a native method and test that its arguments are considered local references. + + // Null as object should fail. + CheckJniAbortCatcher jni_abort_catcher; + EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(nullptr)); + jni_abort_catcher.Check("java_object == null"); } TEST_F(JniInternalTest, StaleWeakGlobal) { jclass java_lang_Class = env_->FindClass("java/lang/Class"); - ASSERT_TRUE(java_lang_Class != NULL); - jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, NULL); - ASSERT_TRUE(local_ref != NULL); + ASSERT_NE(java_lang_Class, nullptr); + jobjectArray local_ref = env_->NewObjectArray(1, java_lang_Class, nullptr); + ASSERT_NE(local_ref, nullptr); jweak weak_global = env_->NewWeakGlobalRef(local_ref); - ASSERT_TRUE(weak_global != NULL); + ASSERT_NE(weak_global, nullptr); env_->DeleteLocalRef(local_ref); Runtime::Current()->GetHeap()->CollectGarbage(false); // GC should clear the weak global. jobject new_global_ref = env_->NewGlobalRef(weak_global); - EXPECT_TRUE(new_global_ref == NULL); + EXPECT_EQ(new_global_ref, nullptr); jobject new_local_ref = env_->NewLocalRef(weak_global); - EXPECT_TRUE(new_local_ref == NULL); + EXPECT_EQ(new_local_ref, nullptr); } TEST_F(JniInternalTest, NewStringUTF) { - EXPECT_TRUE(env_->NewStringUTF(NULL) == NULL); + EXPECT_EQ(env_->NewStringUTF(nullptr), nullptr); jstring s; s = env_->NewStringUTF(""); - EXPECT_TRUE(s != NULL); + EXPECT_NE(s, nullptr); EXPECT_EQ(0, env_->GetStringLength(s)); EXPECT_EQ(0, env_->GetStringUTFLength(s)); s = env_->NewStringUTF("hello"); - EXPECT_TRUE(s != NULL); + EXPECT_NE(s, nullptr); EXPECT_EQ(5, env_->GetStringLength(s)); EXPECT_EQ(5, env_->GetStringUTFLength(s)); @@ -641,11 +963,11 @@ TEST_F(JniInternalTest, NewString) { jchar chars[] = { 'h', 'i' }; jstring s; s = env_->NewString(chars, 0); - EXPECT_TRUE(s != NULL); + EXPECT_NE(s, nullptr); EXPECT_EQ(0, env_->GetStringLength(s)); EXPECT_EQ(0, env_->GetStringUTFLength(s)); s = env_->NewString(chars, 2); - EXPECT_TRUE(s != NULL); + EXPECT_NE(s, nullptr); EXPECT_EQ(2, env_->GetStringLength(s)); EXPECT_EQ(2, env_->GetStringUTFLength(s)); @@ -654,7 +976,7 @@ TEST_F(JniInternalTest, NewString) { TEST_F(JniInternalTest, NewStringNullCharsZeroLength) { jstring s = env_->NewString(nullptr, 0); - EXPECT_TRUE(s != nullptr); + EXPECT_NE(s, nullptr); EXPECT_EQ(0, env_->GetStringLength(s)); } @@ -678,16 +1000,16 @@ TEST_F(JniInternalTest, GetStringLength_GetStringUTFLength) { TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) { jstring s = env_->NewStringUTF("hello"); - ASSERT_TRUE(s != NULL); + ASSERT_TRUE(s != nullptr); - env_->GetStringRegion(s, -1, 0, NULL); - EXPECT_EXCEPTION(sioobe_); - env_->GetStringRegion(s, 0, -1, NULL); - EXPECT_EXCEPTION(sioobe_); - env_->GetStringRegion(s, 0, 10, NULL); - EXPECT_EXCEPTION(sioobe_); - env_->GetStringRegion(s, 10, 1, NULL); - EXPECT_EXCEPTION(sioobe_); + env_->GetStringRegion(s, -1, 0, nullptr); + ExpectException(sioobe_); + env_->GetStringRegion(s, 0, -1, nullptr); + ExpectException(sioobe_); + env_->GetStringRegion(s, 0, 10, nullptr); + ExpectException(sioobe_); + env_->GetStringRegion(s, 10, 1, nullptr); + ExpectException(sioobe_); jchar chars[4] = { 'x', 'x', 'x', 'x' }; env_->GetStringRegion(s, 1, 2, &chars[1]); @@ -696,20 +1018,20 @@ TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) { EXPECT_EQ('l', chars[2]); EXPECT_EQ('x', chars[3]); - // It's okay for the buffer to be NULL as long as the length is 0. - env_->GetStringRegion(s, 2, 0, NULL); + // It's okay for the buffer to be nullptr as long as the length is 0. + env_->GetStringRegion(s, 2, 0, nullptr); // Even if the offset is invalid... - env_->GetStringRegion(s, 123, 0, NULL); - EXPECT_EXCEPTION(sioobe_); - - env_->GetStringUTFRegion(s, -1, 0, NULL); - EXPECT_EXCEPTION(sioobe_); - env_->GetStringUTFRegion(s, 0, -1, NULL); - EXPECT_EXCEPTION(sioobe_); - env_->GetStringUTFRegion(s, 0, 10, NULL); - EXPECT_EXCEPTION(sioobe_); - env_->GetStringUTFRegion(s, 10, 1, NULL); - EXPECT_EXCEPTION(sioobe_); + env_->GetStringRegion(s, 123, 0, nullptr); + ExpectException(sioobe_); + + env_->GetStringUTFRegion(s, -1, 0, nullptr); + ExpectException(sioobe_); + env_->GetStringUTFRegion(s, 0, -1, nullptr); + ExpectException(sioobe_); + env_->GetStringUTFRegion(s, 0, 10, nullptr); + ExpectException(sioobe_); + env_->GetStringUTFRegion(s, 10, 1, nullptr); + ExpectException(sioobe_); char bytes[4] = { 'x', 'x', 'x', 'x' }; env_->GetStringUTFRegion(s, 1, 2, &bytes[1]); @@ -718,25 +1040,25 @@ TEST_F(JniInternalTest, GetStringRegion_GetStringUTFRegion) { EXPECT_EQ('l', bytes[2]); EXPECT_EQ('x', bytes[3]); - // It's okay for the buffer to be NULL as long as the length is 0. - env_->GetStringUTFRegion(s, 2, 0, NULL); + // It's okay for the buffer to be nullptr as long as the length is 0. + env_->GetStringUTFRegion(s, 2, 0, nullptr); // Even if the offset is invalid... - env_->GetStringUTFRegion(s, 123, 0, NULL); - EXPECT_EXCEPTION(sioobe_); + env_->GetStringUTFRegion(s, 123, 0, nullptr); + ExpectException(sioobe_); } TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) { - // Passing in a NULL jstring is ignored normally, but caught by -Xcheck:jni. + // Passing in a nullptr jstring is ignored normally, but caught by -Xcheck:jni. { CheckJniAbortCatcher check_jni_abort_catcher; - EXPECT_TRUE(env_->GetStringUTFChars(NULL, NULL) == NULL); + EXPECT_EQ(env_->GetStringUTFChars(nullptr, nullptr), nullptr); check_jni_abort_catcher.Check("GetStringUTFChars received null jstring"); } jstring s = env_->NewStringUTF("hello"); - ASSERT_TRUE(s != NULL); + ASSERT_TRUE(s != nullptr); - const char* utf = env_->GetStringUTFChars(s, NULL); + const char* utf = env_->GetStringUTFChars(s, nullptr); EXPECT_STREQ("hello", utf); env_->ReleaseStringUTFChars(s, utf); @@ -749,10 +1071,10 @@ TEST_F(JniInternalTest, GetStringUTFChars_ReleaseStringUTFChars) { TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) { jstring s = env_->NewStringUTF("hello"); - ASSERT_TRUE(s != NULL); + ASSERT_TRUE(s != nullptr); jchar expected[] = { 'h', 'e', 'l', 'l', 'o' }; - const jchar* chars = env_->GetStringChars(s, NULL); + const jchar* chars = env_->GetStringChars(s, nullptr); EXPECT_EQ(expected[0], chars[0]); EXPECT_EQ(expected[1], chars[1]); EXPECT_EQ(expected[2], chars[2]); @@ -773,10 +1095,10 @@ TEST_F(JniInternalTest, GetStringChars_ReleaseStringChars) { TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) { jstring s = env_->NewStringUTF("hello"); - ASSERT_TRUE(s != NULL); + ASSERT_TRUE(s != nullptr); jchar expected[] = { 'h', 'e', 'l', 'l', 'o' }; - const jchar* chars = env_->GetStringCritical(s, NULL); + const jchar* chars = env_->GetStringCritical(s, nullptr); EXPECT_EQ(expected[0], chars[0]); EXPECT_EQ(expected[1], chars[1]); EXPECT_EQ(expected[2], chars[2]); @@ -798,45 +1120,72 @@ TEST_F(JniInternalTest, GetStringCritical_ReleaseStringCritical) { TEST_F(JniInternalTest, GetObjectArrayElement_SetObjectArrayElement) { jclass java_lang_Class = env_->FindClass("java/lang/Class"); - ASSERT_TRUE(java_lang_Class != NULL); + ASSERT_TRUE(java_lang_Class != nullptr); - jobjectArray array = env_->NewObjectArray(1, java_lang_Class, NULL); - EXPECT_TRUE(array != NULL); - EXPECT_TRUE(env_->GetObjectArrayElement(array, 0) == NULL); + jobjectArray array = env_->NewObjectArray(1, java_lang_Class, nullptr); + EXPECT_NE(array, nullptr); + EXPECT_EQ(env_->GetObjectArrayElement(array, 0), nullptr); env_->SetObjectArrayElement(array, 0, java_lang_Class); EXPECT_TRUE(env_->IsSameObject(env_->GetObjectArrayElement(array, 0), java_lang_Class)); // ArrayIndexOutOfBounds for negative index. env_->SetObjectArrayElement(array, -1, java_lang_Class); - EXPECT_EXCEPTION(aioobe_); + ExpectException(aioobe_); // ArrayIndexOutOfBounds for too-large index. env_->SetObjectArrayElement(array, 1, java_lang_Class); - EXPECT_EXCEPTION(aioobe_); + ExpectException(aioobe_); // ArrayStoreException thrown for bad types. env_->SetObjectArrayElement(array, 0, env_->NewStringUTF("not a jclass!")); - EXPECT_EXCEPTION(ase_); + ExpectException(ase_); + + // Null as array should fail. + CheckJniAbortCatcher jni_abort_catcher; + EXPECT_EQ(nullptr, env_->GetObjectArrayElement(nullptr, 0)); + jni_abort_catcher.Check("java_array == null"); + env_->SetObjectArrayElement(nullptr, 0, nullptr); + jni_abort_catcher.Check("java_array == null"); } #define EXPECT_STATIC_PRIMITIVE_FIELD(type, field_name, sig, value1, value2) \ do { \ jfieldID fid = env_->GetStaticFieldID(c, field_name, sig); \ - EXPECT_TRUE(fid != NULL); \ + EXPECT_NE(fid, nullptr); \ env_->SetStatic ## type ## Field(c, fid, value1); \ - EXPECT_TRUE(value1 == env_->GetStatic ## type ## Field(c, fid)); \ + EXPECT_EQ(value1, env_->GetStatic ## type ## Field(c, fid)); \ env_->SetStatic ## type ## Field(c, fid, value2); \ - EXPECT_TRUE(value2 == env_->GetStatic ## type ## Field(c, fid)); \ + EXPECT_EQ(value2, env_->GetStatic ## type ## Field(c, fid)); \ + \ + CheckJniAbortCatcher jni_abort_catcher; \ + env_->GetStatic ## type ## Field(nullptr, fid); \ + jni_abort_catcher.Check("received null jclass"); \ + env_->SetStatic ## type ## Field(nullptr, fid, value1); \ + jni_abort_catcher.Check("received null jclass"); \ + env_->GetStatic ## type ## Field(c, nullptr); \ + jni_abort_catcher.Check("fid == null"); \ + env_->SetStatic ## type ## Field(c, nullptr, value1); \ + jni_abort_catcher.Check("fid == null"); \ } while (false) #define EXPECT_PRIMITIVE_FIELD(instance, type, field_name, sig, value1, value2) \ do { \ jfieldID fid = env_->GetFieldID(c, field_name, sig); \ - EXPECT_TRUE(fid != NULL); \ + EXPECT_NE(fid, nullptr); \ env_->Set ## type ## Field(instance, fid, value1); \ - EXPECT_TRUE(value1 == env_->Get ## type ## Field(instance, fid)); \ + EXPECT_EQ(value1, env_->Get ## type ## Field(instance, fid)); \ env_->Set ## type ## Field(instance, fid, value2); \ - EXPECT_TRUE(value2 == env_->Get ## type ## Field(instance, fid)); \ + EXPECT_EQ(value2, env_->Get ## type ## Field(instance, fid)); \ + \ + CheckJniAbortCatcher jni_abort_catcher; \ + env_->Get ## type ## Field(nullptr, fid); \ + jni_abort_catcher.Check("obj == null"); \ + env_->Set ## type ## Field(nullptr, fid, value1); \ + jni_abort_catcher.Check("obj == null"); \ + env_->Get ## type ## Field(instance, nullptr); \ + jni_abort_catcher.Check("fid == null"); \ + env_->Set ## type ## Field(instance, nullptr, value1); \ + jni_abort_catcher.Check("fid == null"); \ } while (false) @@ -845,14 +1194,14 @@ TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) { Thread::Current()->TransitionFromSuspendedToRunnable(); LoadDex("AllFields"); bool started = runtime_->Start(); - CHECK(started); + ASSERT_TRUE(started); jclass c = env_->FindClass("AllFields"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); jobject o = env_->AllocObject(c); - ASSERT_TRUE(o != NULL); + ASSERT_NE(o, nullptr); - EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", true, false); + EXPECT_STATIC_PRIMITIVE_FIELD(Boolean, "sZ", "Z", JNI_TRUE, JNI_FALSE); EXPECT_STATIC_PRIMITIVE_FIELD(Byte, "sB", "B", 1, 2); EXPECT_STATIC_PRIMITIVE_FIELD(Char, "sC", "C", 'a', 'b'); EXPECT_STATIC_PRIMITIVE_FIELD(Double, "sD", "D", 1.0, 2.0); @@ -861,7 +1210,7 @@ TEST_F(JniInternalTest, GetPrimitiveField_SetPrimitiveField) { EXPECT_STATIC_PRIMITIVE_FIELD(Long, "sJ", "J", 1, 2); EXPECT_STATIC_PRIMITIVE_FIELD(Short, "sS", "S", 1, 2); - EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", true, false); + EXPECT_PRIMITIVE_FIELD(o, Boolean, "iZ", "Z", JNI_TRUE, JNI_FALSE); EXPECT_PRIMITIVE_FIELD(o, Byte, "iB", "B", 1, 2); EXPECT_PRIMITIVE_FIELD(o, Char, "iC", "C", 'a', 'b'); EXPECT_PRIMITIVE_FIELD(o, Double, "iD", "D", 1.0, 2.0); @@ -878,19 +1227,19 @@ TEST_F(JniInternalTest, GetObjectField_SetObjectField) { runtime_->Start(); jclass c = env_->FindClass("AllFields"); - ASSERT_TRUE(c != NULL); + ASSERT_NE(c, nullptr); jobject o = env_->AllocObject(c); - ASSERT_TRUE(o != NULL); + ASSERT_NE(o, nullptr); jstring s1 = env_->NewStringUTF("hello"); - ASSERT_TRUE(s1 != NULL); + ASSERT_NE(s1, nullptr); jstring s2 = env_->NewStringUTF("world"); - ASSERT_TRUE(s2 != NULL); + ASSERT_NE(s2, nullptr); jfieldID s_fid = env_->GetStaticFieldID(c, "sObject", "Ljava/lang/Object;"); - ASSERT_TRUE(s_fid != NULL); + ASSERT_NE(s_fid, nullptr); jfieldID i_fid = env_->GetFieldID(c, "iObject", "Ljava/lang/Object;"); - ASSERT_TRUE(i_fid != NULL); + ASSERT_NE(i_fid, nullptr); env_->SetStaticObjectField(c, s_fid, s1); ASSERT_TRUE(env_->IsSameObject(s1, env_->GetStaticObjectField(c, s_fid))); @@ -903,27 +1252,27 @@ TEST_F(JniInternalTest, GetObjectField_SetObjectField) { ASSERT_TRUE(env_->IsSameObject(s2, env_->GetObjectField(o, i_fid))); } -TEST_F(JniInternalTest, NewLocalRef_NULL) { - EXPECT_TRUE(env_->NewLocalRef(NULL) == NULL); +TEST_F(JniInternalTest, NewLocalRef_nullptr) { + EXPECT_EQ(env_->NewLocalRef(nullptr), nullptr); } TEST_F(JniInternalTest, NewLocalRef) { jstring s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); jobject o = env_->NewLocalRef(s); - EXPECT_TRUE(o != NULL); - EXPECT_TRUE(o != s); + EXPECT_NE(o, nullptr); + EXPECT_NE(o, s); EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(o)); } -TEST_F(JniInternalTest, DeleteLocalRef_NULL) { - env_->DeleteLocalRef(NULL); +TEST_F(JniInternalTest, DeleteLocalRef_nullptr) { + env_->DeleteLocalRef(nullptr); } TEST_F(JniInternalTest, DeleteLocalRef) { jstring s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); env_->DeleteLocalRef(s); // Currently, deleting an already-deleted reference is just a CheckJNI warning. @@ -937,9 +1286,9 @@ TEST_F(JniInternalTest, DeleteLocalRef) { } s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); jobject o = env_->NewLocalRef(s); - ASSERT_TRUE(o != NULL); + ASSERT_NE(o, nullptr); env_->DeleteLocalRef(s); env_->DeleteLocalRef(o); @@ -951,7 +1300,7 @@ TEST_F(JniInternalTest, PushLocalFrame_10395422) { // Android historically treated it, and it's how the RI treats it. It's also the more useful // interpretation! ASSERT_EQ(JNI_OK, env_->PushLocalFrame(0)); - env_->PopLocalFrame(NULL); + env_->PopLocalFrame(nullptr); // Negative capacities are not allowed. ASSERT_EQ(JNI_ERR, env_->PushLocalFrame(-1)); @@ -962,7 +1311,7 @@ TEST_F(JniInternalTest, PushLocalFrame_10395422) { TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { jobject original = env_->NewStringUTF(""); - ASSERT_TRUE(original != NULL); + ASSERT_NE(original, nullptr); jobject outer; jobject inner1, inner2; @@ -988,7 +1337,7 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { // gets a new local reference... EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); - env_->PopLocalFrame(NULL); + env_->PopLocalFrame(nullptr); } EXPECT_EQ(JNILocalRefType, env_->GetObjectRefType(original)); EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(outer)); @@ -996,30 +1345,30 @@ TEST_F(JniInternalTest, PushLocalFrame_PopLocalFrame) { EXPECT_EQ(JNIInvalidRefType, env_->GetObjectRefType(inner2)); } -TEST_F(JniInternalTest, NewGlobalRef_NULL) { - EXPECT_TRUE(env_->NewGlobalRef(NULL) == NULL); +TEST_F(JniInternalTest, NewGlobalRef_nullptr) { + EXPECT_EQ(env_->NewGlobalRef(nullptr), nullptr); } TEST_F(JniInternalTest, NewGlobalRef) { jstring s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); jobject o = env_->NewGlobalRef(s); - EXPECT_TRUE(o != NULL); - EXPECT_TRUE(o != s); + EXPECT_NE(o, nullptr); + EXPECT_NE(o, s); - // TODO: check that o is a global reference. + EXPECT_EQ(env_->GetObjectRefType(o), JNIGlobalRefType); } -TEST_F(JniInternalTest, DeleteGlobalRef_NULL) { - env_->DeleteGlobalRef(NULL); +TEST_F(JniInternalTest, DeleteGlobalRef_nullptr) { + env_->DeleteGlobalRef(nullptr); } TEST_F(JniInternalTest, DeleteGlobalRef) { jstring s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); jobject o = env_->NewGlobalRef(s); - ASSERT_TRUE(o != NULL); + ASSERT_NE(o, nullptr); env_->DeleteGlobalRef(o); // Currently, deleting an already-deleted reference is just a CheckJNI warning. @@ -1033,38 +1382,38 @@ TEST_F(JniInternalTest, DeleteGlobalRef) { } jobject o1 = env_->NewGlobalRef(s); - ASSERT_TRUE(o1 != NULL); + ASSERT_NE(o1, nullptr); jobject o2 = env_->NewGlobalRef(s); - ASSERT_TRUE(o2 != NULL); + ASSERT_NE(o2, nullptr); env_->DeleteGlobalRef(o1); env_->DeleteGlobalRef(o2); } -TEST_F(JniInternalTest, NewWeakGlobalRef_NULL) { - EXPECT_TRUE(env_->NewWeakGlobalRef(NULL) == NULL); +TEST_F(JniInternalTest, NewWeakGlobalRef_nullptr) { + EXPECT_EQ(env_->NewWeakGlobalRef(nullptr), nullptr); } TEST_F(JniInternalTest, NewWeakGlobalRef) { jstring s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); jobject o = env_->NewWeakGlobalRef(s); - EXPECT_TRUE(o != NULL); - EXPECT_TRUE(o != s); + EXPECT_NE(o, nullptr); + EXPECT_NE(o, s); - // TODO: check that o is a weak global reference. + EXPECT_EQ(env_->GetObjectRefType(o), JNIWeakGlobalRefType); } -TEST_F(JniInternalTest, DeleteWeakGlobalRef_NULL) { - env_->DeleteWeakGlobalRef(NULL); +TEST_F(JniInternalTest, DeleteWeakGlobalRef_nullptr) { + env_->DeleteWeakGlobalRef(nullptr); } TEST_F(JniInternalTest, DeleteWeakGlobalRef) { jstring s = env_->NewStringUTF(""); - ASSERT_TRUE(s != NULL); + ASSERT_NE(s, nullptr); jobject o = env_->NewWeakGlobalRef(s); - ASSERT_TRUE(o != NULL); + ASSERT_NE(o, nullptr); env_->DeleteWeakGlobalRef(o); // Currently, deleting an already-deleted reference is just a CheckJNI warning. @@ -1078,21 +1427,21 @@ TEST_F(JniInternalTest, DeleteWeakGlobalRef) { } jobject o1 = env_->NewWeakGlobalRef(s); - ASSERT_TRUE(o1 != NULL); + ASSERT_NE(o1, nullptr); jobject o2 = env_->NewWeakGlobalRef(s); - ASSERT_TRUE(o2 != NULL); + ASSERT_NE(o2, nullptr); env_->DeleteWeakGlobalRef(o1); env_->DeleteWeakGlobalRef(o2); } TEST_F(JniInternalTest, Throw) { - EXPECT_EQ(JNI_ERR, env_->Throw(NULL)); + EXPECT_EQ(JNI_ERR, env_->Throw(nullptr)); jclass exception_class = env_->FindClass("java/lang/RuntimeException"); - ASSERT_TRUE(exception_class != NULL); + ASSERT_TRUE(exception_class != nullptr); jthrowable exception = reinterpret_cast<jthrowable>(env_->AllocObject(exception_class)); - ASSERT_TRUE(exception != NULL); + ASSERT_TRUE(exception != nullptr); EXPECT_EQ(JNI_OK, env_->Throw(exception)); EXPECT_TRUE(env_->ExceptionCheck()); @@ -1102,10 +1451,10 @@ TEST_F(JniInternalTest, Throw) { } TEST_F(JniInternalTest, ThrowNew) { - EXPECT_EQ(JNI_ERR, env_->Throw(NULL)); + EXPECT_EQ(JNI_ERR, env_->Throw(nullptr)); jclass exception_class = env_->FindClass("java/lang/RuntimeException"); - ASSERT_TRUE(exception_class != NULL); + ASSERT_TRUE(exception_class != nullptr); jthrowable thrown_exception; @@ -1115,7 +1464,7 @@ TEST_F(JniInternalTest, ThrowNew) { env_->ExceptionClear(); EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, exception_class)); - EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, NULL)); + EXPECT_EQ(JNI_OK, env_->ThrowNew(exception_class, nullptr)); EXPECT_TRUE(env_->ExceptionCheck()); thrown_exception = env_->ExceptionOccurred(); env_->ExceptionClear(); @@ -1141,26 +1490,26 @@ TEST_F(JniInternalTest, NewDirectBuffer_GetDirectBufferAddress_GetDirectBufferCa ASSERT_TRUE(started); jclass buffer_class = env_->FindClass("java/nio/Buffer"); - ASSERT_TRUE(buffer_class != NULL); + ASSERT_NE(buffer_class, nullptr); char bytes[1024]; jobject buffer = env_->NewDirectByteBuffer(bytes, sizeof(bytes)); - ASSERT_TRUE(buffer != NULL); + ASSERT_NE(buffer, nullptr); ASSERT_TRUE(env_->IsInstanceOf(buffer, buffer_class)); - ASSERT_TRUE(env_->GetDirectBufferAddress(buffer) == bytes); - ASSERT_TRUE(env_->GetDirectBufferCapacity(buffer) == sizeof(bytes)); + ASSERT_EQ(env_->GetDirectBufferAddress(buffer), bytes); + ASSERT_EQ(env_->GetDirectBufferCapacity(buffer), static_cast<jlong>(sizeof(bytes))); } TEST_F(JniInternalTest, MonitorEnterExit) { - // Create an object to torture + // Create an object to torture. jclass object_class = env_->FindClass("java/lang/Object"); - ASSERT_TRUE(object_class != NULL); + ASSERT_NE(object_class, nullptr); jobject object = env_->AllocObject(object_class); - ASSERT_TRUE(object != NULL); + ASSERT_NE(object, nullptr); // Expected class of exceptions jclass imse_class = env_->FindClass("java/lang/IllegalMonitorStateException"); - ASSERT_TRUE(imse_class != NULL); + ASSERT_NE(imse_class, nullptr); jthrowable thrown_exception; @@ -1197,13 +1546,13 @@ TEST_F(JniInternalTest, MonitorEnterExit) { env_->ExceptionClear(); EXPECT_TRUE(env_->IsInstanceOf(thrown_exception, imse_class)); - // It's an error to call MonitorEnter or MonitorExit on NULL. + // It's an error to call MonitorEnter or MonitorExit on nullptr. { CheckJniAbortCatcher check_jni_abort_catcher; - env_->MonitorEnter(NULL); + env_->MonitorEnter(nullptr); check_jni_abort_catcher.Check("in call to MonitorEnter"); - env_->MonitorExit(NULL); + env_->MonitorExit(nullptr); check_jni_abort_catcher.Check("in call to MonitorExit"); } } @@ -1215,7 +1564,7 @@ TEST_F(JniInternalTest, DetachCurrentThread) { jint err = vm_->DetachCurrentThread(); EXPECT_EQ(JNI_ERR, err); - vm_->AttachCurrentThread(&env_, NULL); // need attached thread for CommonRuntimeTest::TearDown + vm_->AttachCurrentThread(&env_, nullptr); // need attached thread for CommonRuntimeTest::TearDown } } // namespace art diff --git a/runtime/mirror/array.h b/runtime/mirror/array.h index 238506e86d..1b8106e05f 100644 --- a/runtime/mirror/array.h +++ b/runtime/mirror/array.h @@ -155,14 +155,19 @@ class MANAGED PrimitiveArray : public Array { SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); static void SetArrayClass(Class* array_class) { - CHECK(array_class_ == NULL); - CHECK(array_class != NULL); + CHECK(array_class_ == nullptr); + CHECK(array_class != nullptr); array_class_ = array_class; } + static Class* GetArrayClass() { + DCHECK(array_class_ != nullptr); + return array_class_; + } + static void ResetArrayClass() { - CHECK(array_class_ != NULL); - array_class_ = NULL; + CHECK(array_class_ != nullptr); + array_class_ = nullptr; } static void VisitRoots(RootCallback* callback, void* arg) diff --git a/runtime/native/dalvik_system_VMRuntime.cc b/runtime/native/dalvik_system_VMRuntime.cc index 50a8e47ee6..8d183dad8b 100644 --- a/runtime/native/dalvik_system_VMRuntime.cc +++ b/runtime/native/dalvik_system_VMRuntime.cc @@ -66,10 +66,6 @@ static jobject VMRuntime_newNonMovableArray(JNIEnv* env, jobject, jclass javaEle ThrowNullPointerException(NULL, "element class == null"); return nullptr; } - if (UNLIKELY(element_class->IsPrimitiveVoid())) { - ThrowIllegalArgumentException(NULL, "Can't allocate an array of void"); - return nullptr; - } Runtime* runtime = Runtime::Current(); mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class); if (UNLIKELY(array_class == nullptr)) { @@ -93,10 +89,6 @@ static jobject VMRuntime_newUnpaddedArray(JNIEnv* env, jobject, jclass javaEleme ThrowNullPointerException(NULL, "element class == null"); return nullptr; } - if (UNLIKELY(element_class->IsPrimitiveVoid())) { - ThrowIllegalArgumentException(NULL, "Can't allocate an array of void"); - return nullptr; - } Runtime* runtime = Runtime::Current(); mirror::Class* array_class = runtime->GetClassLinker()->FindArrayClass(soa.Self(), element_class); if (UNLIKELY(array_class == nullptr)) { diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc index 623b0c6b22..55b6a270e0 100644 --- a/runtime/parsed_options.cc +++ b/runtime/parsed_options.cc @@ -689,9 +689,7 @@ bool ParsedOptions::Parse(const Runtime::Options& options, bool ignore_unrecogni if (compiler_callbacks_ == nullptr && image_.empty()) { image_ += GetAndroidRoot(); - image_ += "/framework/boot-"; - image_ += GetInstructionSetString(image_isa_); - image_ += ".art"; + image_ += "/framework/boot.art"; } if (heap_growth_limit_ == 0) { heap_growth_limit_ = heap_maximum_size_; |