diff options
Diffstat (limited to 'runtime/jni_internal.cc')
-rw-r--r-- | runtime/jni_internal.cc | 161 |
1 files changed, 30 insertions, 131 deletions
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc index 6efff1a..43db7ec 100644 --- a/runtime/jni_internal.cc +++ b/runtime/jni_internal.cc @@ -30,7 +30,6 @@ #include "dex_file-inl.h" #include "gc/accounting/card_table-inl.h" #include "interpreter/interpreter.h" -#include "invoke_arg_array_builder.h" #include "jni.h" #include "mirror/art_field-inl.h" #include "mirror/art_method-inl.h" @@ -41,6 +40,7 @@ #include "mirror/throwable.h" #include "object_utils.h" #include "parsed_options.h" +#include "reflection.h" #include "runtime.h" #include "safe_map.h" #include "scoped_thread_state_change.h" @@ -77,104 +77,6 @@ static bool IsBadJniVersion(int version) { return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6; } -static void CheckMethodArguments(mirror::ArtMethod* m, uint32_t* args) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - const DexFile::TypeList* params = MethodHelper(m).GetParameterTypeList(); - if (params == nullptr) { - return; // No arguments so nothing to check. - } - uint32_t offset = 0; - uint32_t num_params = params->Size(); - size_t error_count = 0; - if (!m->IsStatic()) { - offset = 1; - } - for (uint32_t i = 0; i < num_params; i++) { - uint16_t type_idx = params->GetTypeItem(i).type_idx_; - mirror::Class* param_type = MethodHelper(m).GetClassFromTypeIdx(type_idx); - if (param_type == nullptr) { - Thread* self = Thread::Current(); - CHECK(self->IsExceptionPending()); - LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: " - << MethodHelper(m).GetTypeDescriptorFromTypeIdx(type_idx) << "\n" - << self->GetException(nullptr)->Dump(); - self->ClearException(); - ++error_count; - } else if (!param_type->IsPrimitive()) { - // TODO: check primitives are in range. - mirror::Object* argument = reinterpret_cast<mirror::Object*>(args[i + offset]); - if (argument != nullptr && !argument->InstanceOf(param_type)) { - LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of " - << PrettyTypeOf(argument) << " as argument " << (i + 1) - << " to " << PrettyMethod(m); - ++error_count; - } - } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) { - offset++; - } - } - if (error_count > 0) { - // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort - // with an argument. - JniAbortF(nullptr, "bad arguments passed to %s (see above for details)", - PrettyMethod(m).c_str()); - } -} - -void InvokeWithArgArray(const ScopedObjectAccess& soa, mirror::ArtMethod* method, - ArgArray* arg_array, JValue* result, const char* shorty) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - uint32_t* args = arg_array->GetArray(); - if (UNLIKELY(soa.Env()->check_jni)) { - CheckMethodArguments(method, args); - } - method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty); -} - -static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj, - jmethodID mid, va_list args) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::ArtMethod* method = soa.DecodeMethod(mid); - mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); - MethodHelper mh(method); - JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); - arg_array.BuildArgArray(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); - return result; -} - -static mirror::ArtMethod* FindVirtualMethod(mirror::Object* receiver, mirror::ArtMethod* method) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method); -} - -static JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccess& soa, - jobject obj, jmethodID mid, jvalue* args) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); - mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); - MethodHelper mh(method); - JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); - arg_array.BuildArgArray(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); - return result; -} - -static JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccess& soa, - jobject obj, jmethodID mid, va_list args) - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { - mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); - mirror::ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); - MethodHelper mh(method); - JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); - arg_array.BuildArgArray(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); - return result; -} - // Section 12.3.2 of the JNI spec describes JNI class descriptors. They're // separated with slashes but aren't wrapped with "L;" like regular descriptors // (i.e. "a/b/C" rather than "La/b/C;"). Arrays of reference types are an @@ -611,18 +513,6 @@ class Libraries { SafeMap<std::string, SharedLibrary*> libraries_; }; -JValue InvokeWithJValues(const ScopedObjectAccess& soa, jobject obj, jmethodID mid, - jvalue* args) { - mirror::ArtMethod* method = soa.DecodeMethod(mid); - mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); - MethodHelper mh(method); - JValue result; - ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength()); - arg_array.BuildArgArray(soa, receiver, args); - InvokeWithArgArray(soa, method, &arg_array, &result, mh.GetShorty()); - return result; -} - #define CHECK_NON_NULL_ARGUMENT(fn, value) \ if (UNLIKELY(value == nullptr)) { \ JniAbortF(#fn, #value " == null"); \ @@ -1014,7 +904,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallObjectMethodA, mid); ScopedObjectAccess soa(env); - JValue result(InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args)); + JValue result(InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args)); return soa.AddLocalReference<jobject>(result.GetL()); } @@ -1040,7 +931,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallBooleanMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetZ(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetZ(); } static jbyte CallByteMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1065,7 +957,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallByteMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallByteMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetB(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetB(); } static jchar CallCharMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1090,7 +983,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallCharMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallCharMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetC(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetC(); } static jdouble CallDoubleMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1115,7 +1009,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallDoubleMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetD(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetD(); } static jfloat CallFloatMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1140,7 +1035,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallFloatMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetF(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetF(); } static jint CallIntMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1165,7 +1061,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallIntMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallIntMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetI(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetI(); } static jlong CallLongMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1190,7 +1087,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallLongMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallLongMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetJ(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetJ(); } static jshort CallShortMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1215,7 +1113,8 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallShortMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallShortMethodA, mid); ScopedObjectAccess soa(env); - return InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args).GetS(); + return InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, + args).GetS(); } static void CallVoidMethod(JNIEnv* env, jobject obj, jmethodID mid, ...) { @@ -1239,7 +1138,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallVoidMethodA, mid); ScopedObjectAccess soa(env); - InvokeVirtualOrInterfaceWithJValues(soa, obj, mid, args); + InvokeVirtualOrInterfaceWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args); } static jobject CallNonvirtualObjectMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1268,7 +1167,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualObjectMethodA, mid); ScopedObjectAccess soa(env); - JValue result(InvokeWithJValues(soa, obj, mid, args)); + JValue result(InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args)); return soa.AddLocalReference<jobject>(result.GetL()); } @@ -1297,7 +1196,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualBooleanMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetZ(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetZ(); } static jbyte CallNonvirtualByteMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1324,7 +1223,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualByteMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetB(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetB(); } static jchar CallNonvirtualCharMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1351,7 +1250,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualCharMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetC(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetC(); } static jshort CallNonvirtualShortMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1378,7 +1277,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualShortMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetS(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetS(); } static jint CallNonvirtualIntMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1405,7 +1304,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualIntMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetI(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetI(); } static jlong CallNonvirtualLongMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1432,7 +1331,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualLongMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetJ(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetJ(); } static jfloat CallNonvirtualFloatMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1459,7 +1358,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualFloatMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetF(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetF(); } static jdouble CallNonvirtualDoubleMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1486,7 +1385,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualDoubleMethodA, mid); ScopedObjectAccess soa(env); - return InvokeWithJValues(soa, obj, mid, args).GetD(); + return InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args).GetD(); } static void CallNonvirtualVoidMethod(JNIEnv* env, jobject obj, jclass, jmethodID mid, ...) { @@ -1512,7 +1411,7 @@ class JNI { CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, obj); CHECK_NON_NULL_ARGUMENT(CallNonvirtualVoidMethodA, mid); ScopedObjectAccess soa(env); - InvokeWithJValues(soa, obj, mid, args); + InvokeWithJValues(soa, soa.Decode<mirror::Object*>(obj), mid, args); } static jfieldID GetFieldID(JNIEnv* env, jclass java_class, const char* name, const char* sig) { |