Refactor java.lang.reflect implementation
Cherry-picked from commit ed41d5c44299ec5d44b8514f6e17f802f48094d1.
Move to ArtMethod/Field instead of AbstractMethod/Field and have
java.lang.reflect APIs delegate to ArtMethod/ArtField.
Bug: 10014286.
Change-Id: Iafc1d8c5b62562c9af8fb9fd8c5e1d61270536e7
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index d1de6e6..852dd00 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -32,10 +32,10 @@
#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"
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
-#include "mirror/field-inl.h"
-#include "mirror/abstract_method-inl.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/throwable.h"
@@ -49,7 +49,8 @@
#include "UniquePtr.h"
#include "well_known_classes.h"
-using ::art::mirror::AbstractMethod;
+using ::art::mirror::ArtField;
+using ::art::mirror::ArtMethod;
using ::art::mirror::Array;
using ::art::mirror::BooleanArray;
using ::art::mirror::ByteArray;
@@ -57,7 +58,6 @@
using ::art::mirror::Class;
using ::art::mirror::ClassLoader;
using ::art::mirror::DoubleArray;
-using ::art::mirror::Field;
using ::art::mirror::FloatArray;
using ::art::mirror::IntArray;
using ::art::mirror::LongArray;
@@ -101,7 +101,7 @@
return version != JNI_VERSION_1_2 && version != JNI_VERSION_1_4 && version != JNI_VERSION_1_6;
}
-static void CheckMethodArguments(AbstractMethod* m, uint32_t* args)
+static void CheckMethodArguments(ArtMethod* m, uint32_t* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
MethodHelper mh(m);
const DexFile::TypeList* params = mh.GetParameterTypeList();
@@ -144,7 +144,7 @@
}
}
-void InvokeWithArgArray(const ScopedObjectAccess& soa, AbstractMethod* method,
+void InvokeWithArgArray(const ScopedObjectAccess& soa, ArtMethod* method,
ArgArray* arg_array, JValue* result, char result_type)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
uint32_t* args = arg_array->GetArray();
@@ -157,7 +157,7 @@
static JValue InvokeWithVarArgs(const ScopedObjectAccess& soa, jobject obj,
jmethodID mid, va_list args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- AbstractMethod* method = soa.DecodeMethod(mid);
+ ArtMethod* method = soa.DecodeMethod(mid);
Object* receiver = method->IsStatic() ? NULL : soa.Decode<Object*>(obj);
MethodHelper mh(method);
JValue result;
@@ -167,7 +167,7 @@
return result;
}
-static AbstractMethod* FindVirtualMethod(Object* receiver, AbstractMethod* method)
+static ArtMethod* FindVirtualMethod(Object* receiver, ArtMethod* method)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method);
}
@@ -176,7 +176,7 @@
jobject obj, jmethodID mid, jvalue* args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Object* receiver = soa.Decode<Object*>(obj);
- AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
+ ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
MethodHelper mh(method);
JValue result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
@@ -189,7 +189,7 @@
jobject obj, jmethodID mid, va_list args)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
Object* receiver = soa.Decode<Object*>(obj);
- AbstractMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
+ ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid));
MethodHelper mh(method);
JValue result;
ArgArray arg_array(mh.GetShorty(), mh.GetShortyLength());
@@ -239,7 +239,7 @@
return NULL;
}
- AbstractMethod* method = NULL;
+ ArtMethod* method = NULL;
if (is_static) {
method = c->FindDirectMethod(name, sig);
} else {
@@ -261,7 +261,7 @@
static ClassLoader* GetClassLoader(const ScopedObjectAccess& soa)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
- AbstractMethod* method = soa.Self()->GetCurrentMethod(NULL);
+ ArtMethod* method = soa.Self()->GetCurrentMethod(NULL);
if (method == NULL ||
method == soa.DecodeMethod(WellKnownClasses::java_lang_Runtime_nativeLoad)) {
return soa.Self()->GetClassLoaderOverride();
@@ -277,7 +277,7 @@
return NULL;
}
- Field* field = NULL;
+ ArtField* field = NULL;
Class* field_type;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (sig[1] != '\0') {
@@ -290,7 +290,7 @@
// Failed to find type from the signature of the field.
DCHECK(soa.Self()->IsExceptionPending());
ThrowLocation throw_location;
- SirtRef<mirror::Throwable> cause(soa.Self(), soa.Self()->GetException(&throw_location));
+ SirtRef<Throwable> cause(soa.Self(), soa.Self()->GetException(&throw_location));
soa.Self()->ClearException();
soa.Self()->ThrowNewExceptionF(throw_location, "Ljava/lang/NoSuchFieldError;",
"no type \"%s\" found and so no field \"%s\" could be found in class "
@@ -561,7 +561,7 @@
}
// See section 11.3 "Linking Native Methods" of the JNI spec.
- void* FindNativeMethod(const AbstractMethod* m, std::string& detail)
+ void* FindNativeMethod(const ArtMethod* m, std::string& detail)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
std::string jni_short_name(JniShortName(m));
std::string jni_long_name(JniLongName(m));
@@ -598,7 +598,7 @@
JValue InvokeWithJValues(const ScopedObjectAccess& soa, jobject obj, jmethodID mid,
jvalue* args) {
- AbstractMethod* method = soa.DecodeMethod(mid);
+ ArtMethod* method = soa.DecodeMethod(mid);
Object* receiver = method->IsStatic() ? NULL : soa.Decode<Object*>(obj);
MethodHelper mh(method);
JValue result;
@@ -620,10 +620,10 @@
}
static jclass FindClass(JNIEnv* env, const char* name) {
- ScopedObjectAccess soa(env);
Runtime* runtime = Runtime::Current();
ClassLinker* class_linker = runtime->GetClassLinker();
std::string descriptor(NormalizeJniClassDescriptor(name));
+ ScopedObjectAccess soa(env);
Class* c = NULL;
if (runtime->IsStarted()) {
ClassLoader* cl = GetClassLoader(soa);
@@ -636,26 +636,50 @@
static jmethodID FromReflectedMethod(JNIEnv* env, jobject java_method) {
ScopedObjectAccess soa(env);
- AbstractMethod* method = soa.Decode<AbstractMethod*>(java_method);
+ jobject art_method = env->GetObjectField(java_method,
+ WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
+ ArtMethod* method = soa.Decode<ArtMethod*>(art_method);
+ DCHECK(method != NULL);
return soa.EncodeMethod(method);
}
static jfieldID FromReflectedField(JNIEnv* env, jobject java_field) {
ScopedObjectAccess soa(env);
- Field* field = soa.Decode<Field*>(java_field);
+ jobject art_field = env->GetObjectField(java_field,
+ WellKnownClasses::java_lang_reflect_Field_artField);
+ ArtField* field = soa.Decode<ArtField*>(art_field);
+ DCHECK(field != NULL);
return soa.EncodeField(field);
}
static jobject ToReflectedMethod(JNIEnv* env, jclass, jmethodID mid, jboolean) {
ScopedObjectAccess soa(env);
- AbstractMethod* method = soa.DecodeMethod(mid);
- return soa.AddLocalReference<jobject>(method);
+ ArtMethod* m = soa.DecodeMethod(mid);
+ jobject art_method = soa.AddLocalReference<jobject>(m);
+ jobject reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+ SetObjectField(env,
+ reflect_method,
+ WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod,
+ art_method);
+ return reflect_method;
}
static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
ScopedObjectAccess soa(env);
- Field* field = soa.DecodeField(fid);
- return soa.AddLocalReference<jobject>(field);
+ ArtField* f = soa.DecodeField(fid);
+ jobject art_field = soa.AddLocalReference<jobject>(f);
+ jobject reflect_field = env->AllocObject(WellKnownClasses::java_lang_reflect_Field);
+ if (env->ExceptionCheck()) {
+ return NULL;
+ }
+ SetObjectField(env,
+ reflect_field,
+ WellKnownClasses::java_lang_reflect_Field_artField,
+ art_field);
+ return reflect_field;
}
static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
@@ -678,7 +702,6 @@
}
static jboolean IsInstanceOf(JNIEnv* env, jobject jobj, jclass java_class) {
- ScopedObjectAccess soa(env);
if (java_class == NULL) {
JniAbortF("IsInstanceOf", "null class (second argument)");
}
@@ -686,6 +709,7 @@
// Note: JNI is different from regular Java instanceof in this respect
return JNI_TRUE;
} else {
+ ScopedObjectAccess soa(env);
Object* obj = soa.Decode<Object*>(jobj);
Class* c = soa.Decode<Class*>(java_class);
return obj->InstanceOf(c) ? JNI_TRUE : JNI_FALSE;
@@ -718,13 +742,13 @@
static void ExceptionDescribe(JNIEnv* env) {
ScopedObjectAccess soa(env);
- SirtRef<mirror::Object> old_throw_this_object(soa.Self(), NULL);
- SirtRef<mirror::AbstractMethod> old_throw_method(soa.Self(), NULL);
- SirtRef<mirror::Throwable> old_exception(soa.Self(), NULL);
+ SirtRef<Object> old_throw_this_object(soa.Self(), NULL);
+ SirtRef<ArtMethod> old_throw_method(soa.Self(), NULL);
+ SirtRef<Throwable> old_exception(soa.Self(), NULL);
uint32_t old_throw_dex_pc;
{
ThrowLocation old_throw_location;
- mirror::Throwable* old_exception_obj = soa.Self()->GetException(&old_throw_location);
+ Throwable* old_exception_obj = soa.Self()->GetException(&old_throw_location);
old_throw_this_object.reset(old_throw_location.GetThis());
old_throw_method.reset(old_throw_location.GetMethod());
old_exception.reset(old_exception_obj);
@@ -855,8 +879,12 @@
}
static jboolean IsSameObject(JNIEnv* env, jobject obj1, jobject obj2) {
- ScopedObjectAccess soa(env);
- return (soa.Decode<Object*>(obj1) == soa.Decode<Object*>(obj2)) ? JNI_TRUE : JNI_FALSE;
+ if (obj1 == obj2) {
+ return JNI_TRUE;
+ } else {
+ ScopedObjectAccess soa(env);
+ return (soa.Decode<Object*>(obj1) == soa.Decode<Object*>(obj2)) ? JNI_TRUE : JNI_FALSE;
+ }
}
static jobject AllocObject(JNIEnv* env, jclass java_class) {
@@ -1316,8 +1344,8 @@
va_end(ap);
}
- static void CallNonvirtualVoidMethodV(JNIEnv* env,
- jobject obj, jclass, jmethodID mid, va_list args) {
+ static void CallNonvirtualVoidMethodV(JNIEnv* env, jobject obj, jclass, jmethodID mid,
+ va_list args) {
ScopedObjectAccess soa(env);
InvokeWithVarArgs(soa, obj, mid, args);
}
@@ -1342,13 +1370,13 @@
static jobject GetObjectField(JNIEnv* env, jobject obj, jfieldID fid) {
ScopedObjectAccess soa(env);
Object* o = soa.Decode<Object*>(obj);
- Field* f = soa.DecodeField(fid);
+ ArtField* f = soa.DecodeField(fid);
return soa.AddLocalReference<jobject>(f->GetObject(o));
}
static jobject GetStaticObjectField(JNIEnv* env, jclass, jfieldID fid) {
ScopedObjectAccess soa(env);
- Field* f = soa.DecodeField(fid);
+ ArtField* f = soa.DecodeField(fid);
return soa.AddLocalReference<jobject>(f->GetObject(f->GetDeclaringClass()));
}
@@ -1356,37 +1384,37 @@
ScopedObjectAccess soa(env);
Object* o = soa.Decode<Object*>(java_object);
Object* v = soa.Decode<Object*>(java_value);
- Field* f = soa.DecodeField(fid);
+ ArtField* f = soa.DecodeField(fid);
f->SetObject(o, v);
}
static void SetStaticObjectField(JNIEnv* env, jclass, jfieldID fid, jobject java_value) {
ScopedObjectAccess soa(env);
Object* v = soa.Decode<Object*>(java_value);
- Field* f = soa.DecodeField(fid);
+ ArtField* f = soa.DecodeField(fid);
f->SetObject(f->GetDeclaringClass(), v);
}
#define GET_PRIMITIVE_FIELD(fn, instance) \
ScopedObjectAccess soa(env); \
Object* o = soa.Decode<Object*>(instance); \
- Field* f = soa.DecodeField(fid); \
+ ArtField* f = soa.DecodeField(fid); \
return f->fn(o)
#define GET_STATIC_PRIMITIVE_FIELD(fn) \
ScopedObjectAccess soa(env); \
- Field* f = soa.DecodeField(fid); \
+ ArtField* f = soa.DecodeField(fid); \
return f->fn(f->GetDeclaringClass())
#define SET_PRIMITIVE_FIELD(fn, instance, value) \
ScopedObjectAccess soa(env); \
Object* o = soa.Decode<Object*>(instance); \
- Field* f = soa.DecodeField(fid); \
+ ArtField* f = soa.DecodeField(fid); \
f->fn(o, value)
#define SET_STATIC_PRIMITIVE_FIELD(fn, value) \
ScopedObjectAccess soa(env); \
- Field* f = soa.DecodeField(fid); \
+ ArtField* f = soa.DecodeField(fid); \
f->fn(f->GetDeclaringClass(), value)
static jboolean GetBooleanField(JNIEnv* env, jobject obj, jfieldID fid) {
@@ -1806,7 +1834,7 @@
static jsize GetArrayLength(JNIEnv* env, jarray java_array) {
ScopedObjectAccess soa(env);
Object* obj = soa.Decode<Object*>(java_array);
- if (!obj->IsArrayInstance()) {
+ if (UNLIKELY(!obj->IsArrayInstance())) {
JniAbortF("GetArrayLength", "not an array: %s", PrettyTypeOf(obj).c_str());
}
Array* array = obj->AsArray();
@@ -1863,12 +1891,12 @@
}
static jobjectArray NewObjectArray(JNIEnv* env, jsize length, jclass element_jclass, jobject initial_element) {
- ScopedObjectAccess soa(env);
if (length < 0) {
JniAbortF("NewObjectArray", "negative array length: %d", length);
}
// Compute the array class corresponding to the given element class.
+ ScopedObjectAccess soa(env);
Class* element_class = soa.Decode<Class*>(element_jclass);
std::string descriptor;
descriptor += "[";
@@ -2080,7 +2108,7 @@
++sig;
}
- AbstractMethod* m = c->FindDirectMethod(name, sig);
+ ArtMethod* m = c->FindDirectMethod(name, sig);
if (m == NULL) {
m = c->FindVirtualMethod(name, sig);
}
@@ -2111,13 +2139,13 @@
VLOG(jni) << "[Unregistering JNI native methods for " << PrettyClass(c) << "]";
for (size_t i = 0; i < c->NumDirectMethods(); ++i) {
- AbstractMethod* m = c->GetDirectMethod(i);
+ ArtMethod* m = c->GetDirectMethod(i);
if (m->IsNative()) {
m->UnregisterNative(soa.Self());
}
}
for (size_t i = 0; i < c->NumVirtualMethods(); ++i) {
- AbstractMethod* m = c->GetVirtualMethod(i);
+ ArtMethod* m = c->GetVirtualMethod(i);
if (m->IsNative()) {
m->UnregisterNative(soa.Self());
}
@@ -2899,7 +2927,7 @@
return was_successful;
}
-void* JavaVMExt::FindCodeForNativeMethod(AbstractMethod* m) {
+void* JavaVMExt::FindCodeForNativeMethod(ArtMethod* m) {
CHECK(m->IsNative());
Class* c = m->GetDeclaringClass();