summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Mathieu Chartier <mathieuc@google.com> 2015-04-16 18:00:39 -0700
committer Mathieu Chartier <mathieuc@google.com> 2015-04-21 15:51:29 -0700
commitfc58af45e342ba9e18bbdf597f205a58ec731658 (patch)
tree3f93906235cb4d2462d237223b72ccf4eedef645
parentbbf02afc641a393d33342976e269218668c07386 (diff)
Add AbstractMethod, Constructor, Method
Moves functionality to ART from libcore. Precursor to moving ArtMethods to native. Mostly performance improvements. N5 perf before (irrelevant results removed): Class_getConstructor 962.87 =========== Class_getDeclaredMethod 2394.37 ============================ Class_getMethod 2509.20 ============================== Class_newInstance 1999.81 ======================= Method_invokeI 1439.02 ================= Method_invokePreBoxedI 1415.82 ================ Method_invokeStaticI 1456.24 ================= Method_invokeStaticPreBoxedI 1427.32 ================= Method_invokeStaticV 814.47 ========= Method_invokeV 816.56 ========= After: benchmark ns linear runtime Class_getConstructor 1302.04 ================ Class_getDeclaredMethod 1459.01 ================== Class_getMethod 1560.40 =================== Class_newInstance 2029.94 ========================= Method_invokeI 1312.89 ================ Method_invokePreBoxedI 1255.01 =============== Method_invokeStaticI 1289.13 =============== Method_invokeStaticPreBoxedI 1196.52 ============== Method_invokeStaticV 790.82 ========= Method_invokeV 791.73 ========= Performance improvements are more than just fixing regressions introduced in: http://android-review.googlesource.com/#/c/146069/ Bug: 19264997 Change-Id: Ife79c469fdb09f30e3aefcfc3e0ce5ed32303fce
-rw-r--r--dalvikvm/dalvikvm.cc1
-rw-r--r--runtime/Android.mk2
-rw-r--r--runtime/class_linker.cc238
-rw-r--r--runtime/class_linker.h4
-rw-r--r--runtime/class_linker_test.cc180
-rw-r--r--runtime/entrypoints/entrypoint_utils.cc13
-rw-r--r--runtime/entrypoints/quick/quick_trampoline_entrypoints.cc6
-rw-r--r--runtime/jni_internal.cc15
-rw-r--r--runtime/mirror/abstract_method.cc44
-rw-r--r--runtime/mirror/abstract_method.h73
-rw-r--r--runtime/mirror/art_method-inl.h2
-rw-r--r--runtime/mirror/art_method.cc36
-rw-r--r--runtime/mirror/art_method.h4
-rw-r--r--runtime/mirror/class.cc22
-rw-r--r--runtime/mirror/class.h6
-rw-r--r--runtime/mirror/field.h7
-rw-r--r--runtime/mirror/method.cc103
-rw-r--r--runtime/mirror/method.h93
-rw-r--r--runtime/native/java_lang_Class.cc234
-rw-r--r--runtime/native/java_lang_reflect_Constructor.cc35
-rw-r--r--runtime/native/java_lang_reflect_Method.cc6
-rw-r--r--runtime/native/java_lang_reflect_Proxy.cc7
-rw-r--r--runtime/proxy_test.cc61
-rw-r--r--runtime/reflection.cc12
-rw-r--r--runtime/reflection.h3
-rw-r--r--runtime/runtime.cc3
-rw-r--r--runtime/well_known_classes.cc2
27 files changed, 912 insertions, 300 deletions
diff --git a/dalvikvm/dalvikvm.cc b/dalvikvm/dalvikvm.cc
index 7839aa8d4c..fd03002f27 100644
--- a/dalvikvm/dalvikvm.cc
+++ b/dalvikvm/dalvikvm.cc
@@ -50,6 +50,7 @@ static bool IsMethodPublic(JNIEnv* env, jclass c, jmethodID method_id) {
int modifiers = env->CallIntMethod(reflected.get(), mid);
static const int PUBLIC = 0x0001; // java.lang.reflect.Modifiers.PUBLIC
if ((modifiers & PUBLIC) == 0) {
+ fprintf(stderr, "Modifiers mismatch\n");
return false;
}
return true;
diff --git a/runtime/Android.mk b/runtime/Android.mk
index d3488fc71f..86201ba308 100644
--- a/runtime/Android.mk
+++ b/runtime/Android.mk
@@ -100,11 +100,13 @@ LIBART_COMMON_SRC_FILES := \
linear_alloc.cc \
mem_map.cc \
memory_region.cc \
+ mirror/abstract_method.cc \
mirror/art_method.cc \
mirror/array.cc \
mirror/class.cc \
mirror/dex_cache.cc \
mirror/field.cc \
+ mirror/method.cc \
mirror/object.cc \
mirror/reference.cc \
mirror/stack_trace_element.cc \
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 4e59217af6..85b245ffd5 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -59,6 +59,7 @@
#include "mirror/dex_cache-inl.h"
#include "mirror/field.h"
#include "mirror/iftable-inl.h"
+#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/proxy.h"
@@ -258,8 +259,8 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
CHECK(!init_done_);
// java_lang_Class comes first, it's needed for AllocClass
- Thread* self = Thread::Current();
- gc::Heap* heap = Runtime::Current()->GetHeap();
+ Thread* const self = Thread::Current();
+ gc::Heap* const heap = Runtime::Current()->GetHeap();
// The GC can't handle an object with a null class since we can't get the size of this object.
heap->IncrementDisableMovingGC(self);
StackHandleScope<64> hs(self); // 64 is picked arbitrarily.
@@ -436,20 +437,19 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
// Object, String and DexCache need to be rerun through FindSystemClass to finish init
mirror::Class::SetStatus(java_lang_Object, mirror::Class::kStatusNotReady, self);
- mirror::Class* Object_class = FindSystemClass(self, "Ljava/lang/Object;");
- CHECK_EQ(java_lang_Object.Get(), Object_class);
+ CHECK_EQ(java_lang_Object.Get(), FindSystemClass(self, "Ljava/lang/Object;"));
CHECK_EQ(java_lang_Object->GetObjectSize(), mirror::Object::InstanceSize());
mirror::Class::SetStatus(java_lang_String, mirror::Class::kStatusNotReady, self);
mirror::Class* String_class = FindSystemClass(self, "Ljava/lang/String;");
- std::ostringstream os1, os2;
- java_lang_String->DumpClass(os1, mirror::Class::kDumpClassFullDetail);
- String_class->DumpClass(os2, mirror::Class::kDumpClassFullDetail);
- CHECK_EQ(java_lang_String.Get(), String_class) << os1.str() << "\n\n" << os2.str();
+ if (java_lang_String.Get() != String_class) {
+ std::ostringstream os1, os2;
+ java_lang_String->DumpClass(os1, mirror::Class::kDumpClassFullDetail);
+ String_class->DumpClass(os2, mirror::Class::kDumpClassFullDetail);
+ LOG(FATAL) << os1.str() << "\n\n" << os2.str();
+ }
CHECK_EQ(java_lang_String->GetObjectSize(), mirror::String::InstanceSize());
mirror::Class::SetStatus(java_lang_DexCache, mirror::Class::kStatusNotReady, self);
- mirror::Class* DexCache_class = FindSystemClass(self, "Ljava/lang/DexCache;");
- CHECK_EQ(java_lang_String.Get(), String_class);
- CHECK_EQ(java_lang_DexCache.Get(), DexCache_class);
+ CHECK_EQ(java_lang_DexCache.Get(), FindSystemClass(self, "Ljava/lang/DexCache;"));
CHECK_EQ(java_lang_DexCache->GetObjectSize(), mirror::DexCache::InstanceSize());
// Setup the primitive array type classes - can't be done until Object has a vtable.
@@ -459,17 +459,14 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
SetClassRoot(kByteArrayClass, FindSystemClass(self, "[B"));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
- mirror::Class* found_char_array_class = FindSystemClass(self, "[C");
- CHECK_EQ(char_array_class.Get(), found_char_array_class);
+ CHECK_EQ(char_array_class.Get(), FindSystemClass(self, "[C"));
SetClassRoot(kShortArrayClass, FindSystemClass(self, "[S"));
mirror::ShortArray::SetArrayClass(GetClassRoot(kShortArrayClass));
- mirror::Class* found_int_array_class = FindSystemClass(self, "[I");
- CHECK_EQ(int_array_class.Get(), found_int_array_class);
+ CHECK_EQ(int_array_class.Get(), FindSystemClass(self, "[I"));
- mirror::Class* found_long_array_class = FindSystemClass(self, "[J");
- CHECK_EQ(long_array_class.Get(), found_long_array_class);
+ CHECK_EQ(long_array_class.Get(), FindSystemClass(self, "[J"));
SetClassRoot(kFloatArrayClass, FindSystemClass(self, "[F"));
mirror::FloatArray::SetArrayClass(GetClassRoot(kFloatArrayClass));
@@ -477,97 +474,101 @@ void ClassLinker::InitWithoutImage(std::vector<std::unique_ptr<const DexFile>> b
SetClassRoot(kDoubleArrayClass, FindSystemClass(self, "[D"));
mirror::DoubleArray::SetArrayClass(GetClassRoot(kDoubleArrayClass));
- mirror::Class* found_class_array_class = FindSystemClass(self, "[Ljava/lang/Class;");
- CHECK_EQ(class_array_class.Get(), found_class_array_class);
+ CHECK_EQ(class_array_class.Get(), FindSystemClass(self, "[Ljava/lang/Class;"));
- mirror::Class* found_object_array_class = FindSystemClass(self, "[Ljava/lang/Object;");
- CHECK_EQ(object_array_class.Get(), found_object_array_class);
+ CHECK_EQ(object_array_class.Get(), FindSystemClass(self, "[Ljava/lang/Object;"));
// Setup the single, global copy of "iftable".
- mirror::Class* java_lang_Cloneable = FindSystemClass(self, "Ljava/lang/Cloneable;");
- CHECK(java_lang_Cloneable != nullptr);
- mirror::Class* java_io_Serializable = FindSystemClass(self, "Ljava/io/Serializable;");
- CHECK(java_io_Serializable != nullptr);
+ auto java_lang_Cloneable = hs.NewHandle(FindSystemClass(self, "Ljava/lang/Cloneable;"));
+ CHECK(java_lang_Cloneable.Get() != nullptr);
+ auto java_io_Serializable = hs.NewHandle(FindSystemClass(self, "Ljava/io/Serializable;"));
+ CHECK(java_io_Serializable.Get() != nullptr);
// We assume that Cloneable/Serializable don't have superinterfaces -- normally we'd have to
// crawl up and explicitly list all of the supers as well.
- {
- mirror::IfTable* array_iftable = array_iftable_.Read();
- array_iftable->SetInterface(0, java_lang_Cloneable);
- array_iftable->SetInterface(1, java_io_Serializable);
- }
-
- // Sanity check Class[] and Object[]'s interfaces.
- CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, class_array_class, 0));
- CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, class_array_class, 1));
- CHECK_EQ(java_lang_Cloneable, mirror::Class::GetDirectInterface(self, object_array_class, 0));
- CHECK_EQ(java_io_Serializable, mirror::Class::GetDirectInterface(self, object_array_class, 1));
+ array_iftable_.Read()->SetInterface(0, java_lang_Cloneable.Get());
+ array_iftable_.Read()->SetInterface(1, java_io_Serializable.Get());
+
+ // Sanity check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread
+ // suspension.
+ CHECK_EQ(java_lang_Cloneable.Get(),
+ mirror::Class::GetDirectInterface(self, class_array_class, 0));
+ CHECK_EQ(java_io_Serializable.Get(),
+ mirror::Class::GetDirectInterface(self, class_array_class, 1));
+ CHECK_EQ(java_lang_Cloneable.Get(),
+ mirror::Class::GetDirectInterface(self, object_array_class, 0));
+ CHECK_EQ(java_io_Serializable.Get(),
+ mirror::Class::GetDirectInterface(self, object_array_class, 1));
// Run Class, ArtField, and ArtMethod through FindSystemClass. This initializes their
// dex_cache_ fields and register them in class_table_.
- mirror::Class* Class_class = FindSystemClass(self, "Ljava/lang/Class;");
- CHECK_EQ(java_lang_Class.Get(), Class_class);
+ CHECK_EQ(java_lang_Class.Get(), FindSystemClass(self, "Ljava/lang/Class;"));
mirror::Class::SetStatus(java_lang_reflect_ArtMethod, mirror::Class::kStatusNotReady, self);
- mirror::Class* Art_method_class = FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;");
- CHECK_EQ(java_lang_reflect_ArtMethod.Get(), Art_method_class);
-
- mirror::Class* String_array_class =
- FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass));
- CHECK_EQ(object_array_string.Get(), String_array_class);
-
- mirror::Class* Art_method_array_class =
- FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass));
- CHECK_EQ(object_array_art_method.Get(), Art_method_array_class);
+ CHECK_EQ(java_lang_reflect_ArtMethod.Get(),
+ FindSystemClass(self, "Ljava/lang/reflect/ArtMethod;"));
+ CHECK_EQ(object_array_string.Get(),
+ FindSystemClass(self, GetClassRootDescriptor(kJavaLangStringArrayClass)));
+ CHECK_EQ(object_array_art_method.Get(),
+ FindSystemClass(self, GetClassRootDescriptor(kJavaLangReflectArtMethodArrayClass)));
// End of special init trickery, subsequent classes may be loaded via FindSystemClass.
// Create java.lang.reflect.Proxy root.
- mirror::Class* java_lang_reflect_Proxy = FindSystemClass(self, "Ljava/lang/reflect/Proxy;");
- SetClassRoot(kJavaLangReflectProxy, java_lang_reflect_Proxy);
+ SetClassRoot(kJavaLangReflectProxy, FindSystemClass(self, "Ljava/lang/reflect/Proxy;"));
// Create java.lang.reflect.Field.class root.
- mirror::Class* java_lang_reflect_Field = FindSystemClass(self, "Ljava/lang/reflect/Field;");
- CHECK(java_lang_reflect_Field != nullptr);
- SetClassRoot(kJavaLangReflectField, java_lang_reflect_Field);
- mirror::Field::SetClass(java_lang_reflect_Field);
+ auto* class_root = FindSystemClass(self, "Ljava/lang/reflect/Field;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangReflectField, class_root);
+ mirror::Field::SetClass(class_root);
// Create java.lang.reflect.Field array root.
- mirror::Class* java_lang_reflect_Field_array =
- FindSystemClass(self, "[Ljava/lang/reflect/Field;");
- CHECK(java_lang_reflect_Field_array != nullptr);
- SetClassRoot(kJavaLangReflectFieldArrayClass, java_lang_reflect_Field_array);
- mirror::Field::SetArrayClass(java_lang_reflect_Field_array);
+ class_root = FindSystemClass(self, "[Ljava/lang/reflect/Field;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangReflectFieldArrayClass, class_root);
+ mirror::Field::SetArrayClass(class_root);
+
+ // Create java.lang.reflect.Constructor.class root and array root.
+ class_root = FindSystemClass(self, "Ljava/lang/reflect/Constructor;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangReflectConstructor, class_root);
+ mirror::Constructor::SetClass(class_root);
+ class_root = FindSystemClass(self, "[Ljava/lang/reflect/Constructor;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangReflectConstructorArrayClass, class_root);
+ mirror::Constructor::SetArrayClass(class_root);
+
+ // Create java.lang.reflect.Method.class root and array root.
+ class_root = FindSystemClass(self, "Ljava/lang/reflect/Method;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangReflectMethod, class_root);
+ mirror::Method::SetClass(class_root);
+ class_root = FindSystemClass(self, "[Ljava/lang/reflect/Method;");
+ CHECK(class_root != nullptr);
+ SetClassRoot(kJavaLangReflectMethodArrayClass, class_root);
+ mirror::Method::SetArrayClass(class_root);
// java.lang.ref classes need to be specially flagged, but otherwise are normal classes
// finish initializing Reference class
mirror::Class::SetStatus(java_lang_ref_Reference, mirror::Class::kStatusNotReady, self);
- mirror::Class* Reference_class = FindSystemClass(self, "Ljava/lang/ref/Reference;");
- CHECK_EQ(java_lang_ref_Reference.Get(), Reference_class);
+ CHECK_EQ(java_lang_ref_Reference.Get(), FindSystemClass(self, "Ljava/lang/ref/Reference;"));
CHECK_EQ(java_lang_ref_Reference->GetObjectSize(), mirror::Reference::InstanceSize());
CHECK_EQ(java_lang_ref_Reference->GetClassSize(), mirror::Reference::ClassSize());
- mirror::Class* java_lang_ref_FinalizerReference =
- FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
- java_lang_ref_FinalizerReference->SetAccessFlags(
- java_lang_ref_FinalizerReference->GetAccessFlags() |
- kAccClassIsReference | kAccClassIsFinalizerReference);
- mirror::Class* java_lang_ref_PhantomReference =
- FindSystemClass(self, "Ljava/lang/ref/PhantomReference;");
- java_lang_ref_PhantomReference->SetAccessFlags(
- java_lang_ref_PhantomReference->GetAccessFlags() |
- kAccClassIsReference | kAccClassIsPhantomReference);
- mirror::Class* java_lang_ref_SoftReference =
- FindSystemClass(self, "Ljava/lang/ref/SoftReference;");
- java_lang_ref_SoftReference->SetAccessFlags(
- java_lang_ref_SoftReference->GetAccessFlags() | kAccClassIsReference);
- mirror::Class* java_lang_ref_WeakReference =
- FindSystemClass(self, "Ljava/lang/ref/WeakReference;");
- java_lang_ref_WeakReference->SetAccessFlags(
- java_lang_ref_WeakReference->GetAccessFlags() |
- kAccClassIsReference | kAccClassIsWeakReference);
+ class_root = FindSystemClass(self, "Ljava/lang/ref/FinalizerReference;");
+ class_root->SetAccessFlags(class_root->GetAccessFlags() |
+ kAccClassIsReference | kAccClassIsFinalizerReference);
+ class_root = FindSystemClass(self, "Ljava/lang/ref/PhantomReference;");
+ class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference |
+ kAccClassIsPhantomReference);
+ class_root = FindSystemClass(self, "Ljava/lang/ref/SoftReference;");
+ class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference);
+ class_root = FindSystemClass(self, "Ljava/lang/ref/WeakReference;");
+ class_root->SetAccessFlags(class_root->GetAccessFlags() | kAccClassIsReference |
+ kAccClassIsWeakReference);
// Setup the ClassLoader, verifying the object_size_.
- mirror::Class* java_lang_ClassLoader = FindSystemClass(self, "Ljava/lang/ClassLoader;");
- CHECK_EQ(java_lang_ClassLoader->GetObjectSize(), mirror::ClassLoader::InstanceSize());
- SetClassRoot(kJavaLangClassLoader, java_lang_ClassLoader);
+ class_root = FindSystemClass(self, "Ljava/lang/ClassLoader;");
+ CHECK_EQ(class_root->GetObjectSize(), mirror::ClassLoader::InstanceSize());
+ SetClassRoot(kJavaLangClassLoader, class_root);
// Set up java.lang.Throwable, java.lang.ClassNotFoundException, and
// java.lang.StackTraceElement as a convenience.
@@ -911,6 +912,10 @@ void ClassLinker::InitFromImage() {
// String class root was set above
mirror::Field::SetClass(GetClassRoot(kJavaLangReflectField));
mirror::Field::SetArrayClass(GetClassRoot(kJavaLangReflectFieldArrayClass));
+ mirror::Constructor::SetClass(GetClassRoot(kJavaLangReflectConstructor));
+ mirror::Constructor::SetArrayClass(GetClassRoot(kJavaLangReflectConstructorArrayClass));
+ mirror::Method::SetClass(GetClassRoot(kJavaLangReflectMethod));
+ mirror::Method::SetArrayClass(GetClassRoot(kJavaLangReflectMethodArrayClass));
mirror::Reference::SetClass(GetClassRoot(kJavaLangRefReference));
mirror::BooleanArray::SetArrayClass(GetClassRoot(kBooleanArrayClass));
mirror::ByteArray::SetArrayClass(GetClassRoot(kByteArrayClass));
@@ -1096,22 +1101,26 @@ void ClassLinker::VisitClassesWithoutClassesLock(ClassVisitor* visitor, void* ar
}
ClassLinker::~ClassLinker() {
- mirror::Class::ResetClass();
- mirror::String::ResetClass();
- mirror::Reference::ResetClass();
mirror::ArtMethod::ResetClass();
+ mirror::Class::ResetClass();
+ mirror::Constructor::ResetClass();
mirror::Field::ResetClass();
- mirror::Field::ResetArrayClass();
+ mirror::Method::ResetClass();
+ mirror::Reference::ResetClass();
+ mirror::StackTraceElement::ResetClass();
+ mirror::String::ResetClass();
+ mirror::Throwable::ResetClass();
mirror::BooleanArray::ResetArrayClass();
mirror::ByteArray::ResetArrayClass();
mirror::CharArray::ResetArrayClass();
+ mirror::Constructor::ResetArrayClass();
mirror::DoubleArray::ResetArrayClass();
+ mirror::Field::ResetArrayClass();
mirror::FloatArray::ResetArrayClass();
+ mirror::Method::ResetArrayClass();
mirror::IntArray::ResetArrayClass();
mirror::LongArray::ResetArrayClass();
mirror::ShortArray::ResetArrayClass();
- mirror::Throwable::ResetClass();
- mirror::StackTraceElement::ResetClass();
STLDeleteElements(&oat_files_);
}
@@ -2947,7 +2956,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
jobjectArray interfaces, jobject loader,
jobjectArray methods, jobjectArray throws) {
Thread* self = soa.Self();
- StackHandleScope<8> hs(self);
+ StackHandleScope<9> hs(self);
MutableHandle<mirror::Class> klass(hs.NewHandle(
AllocClass(self, GetClassRoot(kJavaLangClass), sizeof(mirror::Class))));
if (klass.Get() == nullptr) {
@@ -3001,8 +3010,10 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
}
// Create virtual method using specified prototypes.
- size_t num_virtual_methods =
- soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods)->GetLength();
+ auto h_methods = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Method>*>(methods));
+ DCHECK_EQ(h_methods->GetClass(), mirror::Method::ArrayClass())
+ << PrettyClass(h_methods->GetClass());
+ const size_t num_virtual_methods = h_methods->GetLength();
{
mirror::ObjectArray<mirror::ArtMethod>* virtuals = AllocArtMethodArray(self,
num_virtual_methods);
@@ -3014,9 +3025,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
}
for (size_t i = 0; i < num_virtual_methods; ++i) {
StackHandleScope<1> hs2(self);
- mirror::ObjectArray<mirror::ArtMethod>* decoded_methods =
- soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods);
- Handle<mirror::ArtMethod> prototype(hs2.NewHandle(decoded_methods->Get(i)));
+ Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
mirror::ArtMethod* clone = CreateProxyMethod(self, klass, prototype);
if (UNLIKELY(clone == nullptr)) {
CHECK(self->IsExceptionPending()); // OOME.
@@ -3066,9 +3075,7 @@ mirror::Class* ClassLinker::CreateProxyClass(ScopedObjectAccessAlreadyRunnable&
CheckProxyConstructor(klass->GetDirectMethod(0));
for (size_t i = 0; i < num_virtual_methods; ++i) {
StackHandleScope<2> hs2(self);
- mirror::ObjectArray<mirror::ArtMethod>* decoded_methods =
- soa.Decode<mirror::ObjectArray<mirror::ArtMethod>*>(methods);
- Handle<mirror::ArtMethod> prototype(hs2.NewHandle(decoded_methods->Get(i)));
+ Handle<mirror::ArtMethod> prototype(hs2.NewHandle(h_methods->Get(i)->GetArtMethod()));
Handle<mirror::ArtMethod> virtual_method(hs2.NewHandle(klass->GetVirtualMethod(i)));
CheckProxyMethod(virtual_method, prototype);
}
@@ -3104,23 +3111,22 @@ mirror::ArtMethod* ClassLinker::FindMethodForProxy(mirror::Class* proxy_class,
mirror::ArtMethod* proxy_method) {
DCHECK(proxy_class->IsProxyClass());
DCHECK(proxy_method->IsProxyMethod());
- // Locate the dex cache of the original interface/Object
- mirror::DexCache* dex_cache = nullptr;
{
ReaderMutexLock mu(Thread::Current(), dex_lock_);
- for (size_t i = 0; i != dex_caches_.size(); ++i) {
- mirror::DexCache* a_dex_cache = GetDexCache(i);
- if (proxy_method->HasSameDexCacheResolvedTypes(a_dex_cache->GetResolvedTypes())) {
- dex_cache = a_dex_cache;
- break;
+ // Locate the dex cache of the original interface/Object
+ for (const GcRoot<mirror::DexCache>& root : dex_caches_) {
+ auto* dex_cache = root.Read();
+ if (proxy_method->HasSameDexCacheResolvedTypes(dex_cache->GetResolvedTypes())) {
+ mirror::ArtMethod* resolved_method = dex_cache->GetResolvedMethod(
+ proxy_method->GetDexMethodIndex());
+ CHECK(resolved_method != nullptr);
+ return resolved_method;
}
}
}
- CHECK(dex_cache != nullptr);
- uint32_t method_idx = proxy_method->GetDexMethodIndex();
- mirror::ArtMethod* resolved_method = dex_cache->GetResolvedMethod(method_idx);
- CHECK(resolved_method != nullptr);
- return resolved_method;
+ LOG(FATAL) << "Didn't find dex cache for " << PrettyClass(proxy_class) << " "
+ << PrettyMethod(proxy_method);
+ UNREACHABLE();
}
@@ -3163,8 +3169,11 @@ mirror::ArtMethod* ClassLinker::CreateProxyMethod(Thread* self,
Handle<mirror::ArtMethod> prototype) {
// Ensure prototype is in dex cache so that we can use the dex cache to look up the overridden
// prototype method
- prototype->GetDeclaringClass()->GetDexCache()->SetResolvedMethod(prototype->GetDexMethodIndex(),
- prototype.Get());
+ auto* dex_cache = prototype->GetDeclaringClass()->GetDexCache();
+ // Avoid dirtying the dex cache unless we need to.
+ if (dex_cache->GetResolvedMethod(prototype->GetDexMethodIndex()) != prototype.Get()) {
+ dex_cache->SetResolvedMethod(prototype->GetDexMethodIndex(), prototype.Get());
+ }
// We steal everything from the prototype (such as DexCache, invoke stub, etc.) then specialize
// as necessary
mirror::ArtMethod* method = down_cast<mirror::ArtMethod*>(prototype->Clone(self));
@@ -3198,6 +3207,7 @@ static void CheckProxyMethod(Handle<mirror::ArtMethod> method,
// interface prototype. The exception to this are Constructors and the Class of the Proxy itself.
CHECK(prototype->HasSameDexCacheResolvedMethods(method.Get()));
CHECK(prototype->HasSameDexCacheResolvedTypes(method.Get()));
+ CHECK_EQ(prototype->GetDeclaringClass()->GetDexCache(), method->GetDexCache());
CHECK_EQ(prototype->GetDexMethodIndex(), method->GetDexMethodIndex());
CHECK_STREQ(method->GetName(), prototype->GetName());
@@ -5210,11 +5220,15 @@ const char* ClassLinker::GetClassRootDescriptor(ClassRoot class_root) {
"Ljava/lang/DexCache;",
"Ljava/lang/ref/Reference;",
"Ljava/lang/reflect/ArtMethod;",
+ "Ljava/lang/reflect/Constructor;",
"Ljava/lang/reflect/Field;",
+ "Ljava/lang/reflect/Method;",
"Ljava/lang/reflect/Proxy;",
"[Ljava/lang/String;",
"[Ljava/lang/reflect/ArtMethod;",
+ "[Ljava/lang/reflect/Constructor;",
"[Ljava/lang/reflect/Field;",
+ "[Ljava/lang/reflect/Method;",
"Ljava/lang/ClassLoader;",
"Ljava/lang/Throwable;",
"Ljava/lang/ClassNotFoundException;",
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index 68624b08b6..d7c625da83 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -71,11 +71,15 @@ class ClassLinker {
kJavaLangDexCache,
kJavaLangRefReference,
kJavaLangReflectArtMethod,
+ kJavaLangReflectConstructor,
kJavaLangReflectField,
+ kJavaLangReflectMethod,
kJavaLangReflectProxy,
kJavaLangStringArrayClass,
kJavaLangReflectArtMethodArrayClass,
+ kJavaLangReflectConstructorArrayClass,
kJavaLangReflectFieldArrayClass,
+ kJavaLangReflectMethodArrayClass,
kJavaLangClassLoader,
kJavaLangThrowable,
kJavaLangClassNotFoundException,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index a31a7852c7..7bee98f8f1 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -25,6 +25,7 @@
#include "dex_file.h"
#include "entrypoints/entrypoint_utils-inl.h"
#include "gc/heap.h"
+#include "mirror/abstract_method.h"
#include "mirror/accessible_object.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
@@ -463,6 +464,10 @@ struct CheckOffsets {
return !error;
};
+ void addOffset(size_t offset, const char* name) {
+ offsets.push_back(CheckOffset(offset, name));
+ }
+
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(CheckOffsets);
};
@@ -472,142 +477,162 @@ struct CheckOffsets {
struct ObjectOffsets : public CheckOffsets<mirror::Object> {
ObjectOffsets() : CheckOffsets<mirror::Object>(false, "Ljava/lang/Object;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, klass_), "shadow$_klass_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, monitor_), "shadow$_monitor_"));
+ addOffset(OFFSETOF_MEMBER(mirror::Object, klass_), "shadow$_klass_");
+ addOffset(OFFSETOF_MEMBER(mirror::Object, monitor_), "shadow$_monitor_");
#ifdef USE_BAKER_OR_BROOKS_READ_BARRIER
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_rb_ptr_), "shadow$_x_rb_ptr_"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Object, x_xpadding_), "shadow$_x_xpadding_"));
+ addOffset(OFFSETOF_MEMBER(mirror::Object, x_rb_ptr_), "shadow$_x_rb_ptr_");
+ addOffset(OFFSETOF_MEMBER(mirror::Object, x_xpadding_), "shadow$_x_xpadding_");
#endif
};
};
struct ArtMethodOffsets : public CheckOffsets<mirror::ArtMethod> {
ArtMethodOffsets() : CheckOffsets<mirror::ArtMethod>(false, "Ljava/lang/reflect/ArtMethod;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_), "dexCacheResolvedMethods"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_), "dexCacheResolvedTypes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex"));
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_), "accessFlags");
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, declaring_class_), "declaringClass");
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_methods_),
+ "dexCacheResolvedMethods");
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_cache_resolved_types_),
+ "dexCacheResolvedTypes");
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_code_item_offset_), "dexCodeItemOffset");
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, dex_method_index_), "dexMethodIndex");
+ addOffset(OFFSETOF_MEMBER(mirror::ArtMethod, method_index_), "methodIndex");
};
};
struct ClassOffsets : public CheckOffsets<mirror::Class> {
ClassOffsets() : CheckOffsets<mirror::Class>(false, "Ljava/lang/Class;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_loader_), "classLoader"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, component_type_), "componentType"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_), "dexCache"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_strings_), "dexCacheStrings"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, direct_methods_), "directMethods"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_), "numReferenceInstanceFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_), "numReferenceStaticFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_), "referenceInstanceOffsets"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, sfields_), "sFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, status_), "status"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_class_), "verifyErrorClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_), "virtualMethods"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Class, vtable_), "vtable"));
+ addOffset(OFFSETOF_MEMBER(mirror::Class, access_flags_), "accessFlags");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, class_loader_), "classLoader");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, class_size_), "classSize");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, clinit_thread_id_), "clinitThreadId");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, component_type_), "componentType");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_), "dexCache");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, dex_cache_strings_), "dexCacheStrings");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, dex_class_def_idx_), "dexClassDefIndex");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, dex_type_idx_), "dexTypeIndex");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, direct_methods_), "directMethods");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, ifields_), "iFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, iftable_), "ifTable");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, name_), "name");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, num_instance_fields_), "numInstanceFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_instance_fields_),
+ "numReferenceInstanceFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, num_reference_static_fields_),
+ "numReferenceStaticFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, num_static_fields_), "numStaticFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, object_size_), "objectSize");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, primitive_type_), "primitiveType");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, reference_instance_offsets_),
+ "referenceInstanceOffsets");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, sfields_), "sFields");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, status_), "status");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, super_class_), "superClass");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, verify_error_class_), "verifyErrorClass");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, virtual_methods_), "virtualMethods");
+ addOffset(OFFSETOF_MEMBER(mirror::Class, vtable_), "vtable");
};
};
struct StringOffsets : public CheckOffsets<mirror::String> {
StringOffsets() : CheckOffsets<mirror::String>(false, "Ljava/lang/String;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, count_), "count"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, hash_code_), "hashCode"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, offset_), "offset"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::String, array_), "value"));
+ addOffset(OFFSETOF_MEMBER(mirror::String, count_), "count");
+ addOffset(OFFSETOF_MEMBER(mirror::String, hash_code_), "hashCode");
+ addOffset(OFFSETOF_MEMBER(mirror::String, offset_), "offset");
+ addOffset(OFFSETOF_MEMBER(mirror::String, array_), "value");
};
};
struct ThrowableOffsets : public CheckOffsets<mirror::Throwable> {
ThrowableOffsets() : CheckOffsets<mirror::Throwable>(false, "Ljava/lang/Throwable;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, cause_), "cause"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, detail_message_), "detailMessage"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_state_), "stackState"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_trace_), "stackTrace"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Throwable, suppressed_exceptions_), "suppressedExceptions"));
+ addOffset(OFFSETOF_MEMBER(mirror::Throwable, cause_), "cause");
+ addOffset(OFFSETOF_MEMBER(mirror::Throwable, detail_message_), "detailMessage");
+ addOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_state_), "stackState");
+ addOffset(OFFSETOF_MEMBER(mirror::Throwable, stack_trace_), "stackTrace");
+ addOffset(OFFSETOF_MEMBER(mirror::Throwable, suppressed_exceptions_), "suppressedExceptions");
};
};
struct StackTraceElementOffsets : public CheckOffsets<mirror::StackTraceElement> {
- StackTraceElementOffsets() : CheckOffsets<mirror::StackTraceElement>(false, "Ljava/lang/StackTraceElement;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, declaring_class_), "declaringClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, file_name_), "fileName"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, line_number_), "lineNumber"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, method_name_), "methodName"));
+ StackTraceElementOffsets() : CheckOffsets<mirror::StackTraceElement>(
+ false, "Ljava/lang/StackTraceElement;") {
+ addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, declaring_class_), "declaringClass");
+ addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, file_name_), "fileName");
+ addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, line_number_), "lineNumber");
+ addOffset(OFFSETOF_MEMBER(mirror::StackTraceElement, method_name_), "methodName");
};
};
struct ClassLoaderOffsets : public CheckOffsets<mirror::ClassLoader> {
ClassLoaderOffsets() : CheckOffsets<mirror::ClassLoader>(false, "Ljava/lang/ClassLoader;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, packages_), "packages"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, parent_), "parent"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ClassLoader, proxyCache_), "proxyCache"));
+ addOffset(OFFSETOF_MEMBER(mirror::ClassLoader, packages_), "packages");
+ addOffset(OFFSETOF_MEMBER(mirror::ClassLoader, parent_), "parent");
+ addOffset(OFFSETOF_MEMBER(mirror::ClassLoader, proxyCache_), "proxyCache");
};
};
struct ProxyOffsets : public CheckOffsets<mirror::Proxy> {
ProxyOffsets() : CheckOffsets<mirror::Proxy>(false, "Ljava/lang/reflect/Proxy;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Proxy, h_), "h"));
+ addOffset(OFFSETOF_MEMBER(mirror::Proxy, h_), "h");
};
};
struct DexCacheOffsets : public CheckOffsets<mirror::DexCache> {
DexCacheOffsets() : CheckOffsets<mirror::DexCache>(false, "Ljava/lang/DexCache;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_), "dex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_), "resolvedFields"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_methods_), "resolvedMethods"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_types_), "resolvedTypes"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::DexCache, strings_), "strings"));
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_), "dex");
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, dex_file_), "dexFile");
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, location_), "location");
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_fields_), "resolvedFields");
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_methods_), "resolvedMethods");
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, resolved_types_), "resolvedTypes");
+ addOffset(OFFSETOF_MEMBER(mirror::DexCache, strings_), "strings");
};
};
struct ReferenceOffsets : public CheckOffsets<mirror::Reference> {
ReferenceOffsets() : CheckOffsets<mirror::Reference>(false, "Ljava/lang/ref/Reference;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, pending_next_), "pendingNext"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, queue_), "queue"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, queue_next_), "queueNext"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Reference, referent_), "referent"));
+ addOffset(OFFSETOF_MEMBER(mirror::Reference, pending_next_), "pendingNext");
+ addOffset(OFFSETOF_MEMBER(mirror::Reference, queue_), "queue");
+ addOffset(OFFSETOF_MEMBER(mirror::Reference, queue_next_), "queueNext");
+ addOffset(OFFSETOF_MEMBER(mirror::Reference, referent_), "referent");
};
};
struct FinalizerReferenceOffsets : public CheckOffsets<mirror::FinalizerReference> {
- FinalizerReferenceOffsets() : CheckOffsets<mirror::FinalizerReference>(false, "Ljava/lang/ref/FinalizerReference;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, next_), "next"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, prev_), "prev"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, zombie_), "zombie"));
+ FinalizerReferenceOffsets() : CheckOffsets<mirror::FinalizerReference>(
+ false, "Ljava/lang/ref/FinalizerReference;") {
+ addOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, next_), "next");
+ addOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, prev_), "prev");
+ addOffset(OFFSETOF_MEMBER(mirror::FinalizerReference, zombie_), "zombie");
};
};
struct AccessibleObjectOffsets : public CheckOffsets<mirror::AccessibleObject> {
- AccessibleObjectOffsets() : CheckOffsets<mirror::AccessibleObject>(false, "Ljava/lang/reflect/AccessibleObject;") {
- offsets.push_back(CheckOffset(mirror::AccessibleObject::FlagOffset().Uint32Value(), "flag"));
+ AccessibleObjectOffsets() : CheckOffsets<mirror::AccessibleObject>(
+ false, "Ljava/lang/reflect/AccessibleObject;") {
+ addOffset(mirror::AccessibleObject::FlagOffset().Uint32Value(), "flag");
};
};
struct FieldOffsets : public CheckOffsets<mirror::Field> {
FieldOffsets() : CheckOffsets<mirror::Field>(false, "Ljava/lang/reflect/Field;") {
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, access_flags_), "accessFlags"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, declaring_class_), "declaringClass"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, dex_field_index_), "dexFieldIndex"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, offset_), "offset"));
- offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::Field, type_), "type"));
+ addOffset(OFFSETOF_MEMBER(mirror::Field, access_flags_), "accessFlags");
+ addOffset(OFFSETOF_MEMBER(mirror::Field, declaring_class_), "declaringClass");
+ addOffset(OFFSETOF_MEMBER(mirror::Field, dex_field_index_), "dexFieldIndex");
+ addOffset(OFFSETOF_MEMBER(mirror::Field, offset_), "offset");
+ addOffset(OFFSETOF_MEMBER(mirror::Field, type_), "type");
+ };
+};
+
+struct AbstractMethodOffsets : public CheckOffsets<mirror::AbstractMethod> {
+ AbstractMethodOffsets() : CheckOffsets<mirror::AbstractMethod>(
+ false, "Ljava/lang/reflect/AbstractMethod;") {
+ addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, access_flags_), "accessFlags");
+ addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, art_method_), "artMethod");
+ addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, declaring_class_), "declaringClass");
+ addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, declaring_class_of_overridden_method_),
+ "declaringClassOfOverriddenMethod");
+ addOffset(OFFSETOF_MEMBER(mirror::AbstractMethod, dex_method_index_), "dexMethodIndex");
};
};
@@ -629,6 +654,7 @@ TEST_F(ClassLinkerTest, ValidateFieldOrderOfJavaCppUnionClasses) {
EXPECT_TRUE(FinalizerReferenceOffsets().Check());
EXPECT_TRUE(AccessibleObjectOffsets().Check());
EXPECT_TRUE(FieldOffsets().Check());
+ EXPECT_TRUE(AbstractMethodOffsets().Check());
}
TEST_F(ClassLinkerTest, FindClassNonexistent) {
diff --git a/runtime/entrypoints/entrypoint_utils.cc b/runtime/entrypoints/entrypoint_utils.cc
index 1d8df68994..768f5052d4 100644
--- a/runtime/entrypoints/entrypoint_utils.cc
+++ b/runtime/entrypoints/entrypoint_utils.cc
@@ -23,6 +23,7 @@
#include "gc/accounting/card_table-inl.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
+#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "reflection.h"
@@ -257,7 +258,7 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons
}
}
- // Call Proxy.invoke(Proxy proxy, ArtMethod method, Object[] args).
+ // Call Proxy.invoke(Proxy proxy, Method method, Object[] args).
jvalue invocation_args[3];
invocation_args[0].l = rcvr_jobj;
invocation_args[1].l = interface_method_jobj;
@@ -274,10 +275,9 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons
return zero;
} else {
StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ArtMethod> h_interface_method(
- hs.NewHandle(soa.Decode<mirror::ArtMethod*>(interface_method_jobj)));
+ auto h_interface_method(hs.NewHandle(soa.Decode<mirror::Method*>(interface_method_jobj)));
// This can cause thread suspension.
- mirror::Class* result_type = h_interface_method->GetReturnType();
+ mirror::Class* result_type = h_interface_method->GetArtMethod()->GetReturnType();
mirror::Object* result_ref = soa.Decode<mirror::Object*>(result);
JValue result_unboxed;
if (!UnboxPrimitiveForResult(result_ref, result_type, &result_unboxed)) {
@@ -293,10 +293,9 @@ JValue InvokeProxyInvocationHandler(ScopedObjectAccessAlreadyRunnable& soa, cons
if (exception->IsCheckedException()) {
mirror::Object* rcvr = soa.Decode<mirror::Object*>(rcvr_jobj);
mirror::Class* proxy_class = rcvr->GetClass();
- mirror::ArtMethod* interface_method =
- soa.Decode<mirror::ArtMethod*>(interface_method_jobj);
+ mirror::Method* interface_method = soa.Decode<mirror::Method*>(interface_method_jobj);
mirror::ArtMethod* proxy_method =
- rcvr->GetClass()->FindVirtualMethodForInterface(interface_method);
+ rcvr->GetClass()->FindVirtualMethodForInterface(interface_method->GetArtMethod());
int throws_index = -1;
size_t num_virt_methods = proxy_class->NumVirtualMethods();
for (size_t i = 0; i < num_virt_methods; i++) {
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 2e813c808a..2e7e2dfd74 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -26,6 +26,7 @@
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/dex_cache-inl.h"
+#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "runtime.h"
@@ -760,11 +761,12 @@ extern "C" uint64_t artQuickProxyInvokeHandler(mirror::ArtMethod* proxy_method,
mirror::ArtMethod* interface_method = proxy_method->FindOverriddenMethod();
DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method);
DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
- jobject interface_method_jobj = soa.AddLocalReference<jobject>(interface_method);
+ self->EndAssertNoThreadSuspension(old_cause);
+ jobject interface_method_jobj = soa.AddLocalReference<jobject>(
+ mirror::Method::CreateFromArtMethod(soa.Self(), interface_method));
// All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
// that performs allocations.
- self->EndAssertNoThreadSuspension(old_cause);
JValue result = InvokeProxyInvocationHandler(soa, shorty, rcvr_jobj, interface_method_jobj, args);
// Restore references which might have moved.
local_ref_visitor.FixupReferences();
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 8a5461baee..554a28d3f4 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -42,6 +42,7 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/field-inl.h"
+#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
@@ -361,19 +362,13 @@ class JNI {
ScopedObjectAccess soa(env);
mirror::ArtMethod* m = soa.DecodeMethod(mid);
CHECK(!kMovingMethods);
- ScopedLocalRef<jobject> art_method(env, soa.AddLocalReference<jobject>(m));
- jobject reflect_method;
+ mirror::AbstractMethod* method;
if (m->IsConstructor()) {
- reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Constructor);
+ method = mirror::Constructor::CreateFromArtMethod(soa.Self(), m);
} else {
- reflect_method = env->AllocObject(WellKnownClasses::java_lang_reflect_Method);
+ method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
}
- if (env->ExceptionCheck()) {
- return nullptr;
- }
- SetObjectField(env, reflect_method,
- WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod, art_method.get());
- return reflect_method;
+ return soa.AddLocalReference<jobject>(method);
}
static jobject ToReflectedField(JNIEnv* env, jclass, jfieldID fid, jboolean) {
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
new file mode 100644
index 0000000000..81c656b6fa
--- /dev/null
+++ b/runtime/mirror/abstract_method.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "abstract_method.h"
+
+#include "mirror/art_method-inl.h"
+
+namespace art {
+namespace mirror {
+
+bool AbstractMethod::CreateFromArtMethod(mirror::ArtMethod* method) {
+ auto* interface_method = method->GetInterfaceMethodIfProxy();
+ SetFieldObject<false>(ArtMethodOffset(), method);
+ SetFieldObject<false>(DeclaringClassOffset(), method->GetDeclaringClass());
+ SetFieldObject<false>(
+ DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
+ SetField32<false>(AccessFlagsOffset(), method->GetAccessFlags());
+ SetField32<false>(DexMethodIndexOffset(), method->GetDexMethodIndex());
+ return true;
+}
+
+mirror::ArtMethod* AbstractMethod::GetArtMethod() {
+ return GetFieldObject<mirror::ArtMethod>(ArtMethodOffset());
+}
+
+mirror::Class* AbstractMethod::GetDeclaringClass() {
+ return GetFieldObject<mirror::Class>(DeclaringClassOffset());
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
new file mode 100644
index 0000000000..ef51d7f4ae
--- /dev/null
+++ b/runtime/mirror/abstract_method.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
+#define ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
+
+#include "accessible_object.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+
+namespace art {
+
+struct AbstractMethodOffsets;
+
+namespace mirror {
+
+class ArtMethod;
+
+// C++ mirror of java.lang.reflect.AbstractMethod.
+class MANAGED AbstractMethod : public AccessibleObject {
+ public:
+ // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
+ bool CreateFromArtMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ mirror::ArtMethod* GetArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ static MemberOffset ArtMethodOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, art_method_));
+ }
+ static MemberOffset DeclaringClassOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
+ }
+ static MemberOffset DeclaringClassOfOverriddenMethodOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_of_overridden_method_));
+ }
+ static MemberOffset AccessFlagsOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_));
+ }
+ static MemberOffset DexMethodIndexOffset() {
+ return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, dex_method_index_));
+ }
+
+ HeapReference<mirror::ArtMethod> art_method_;
+ HeapReference<mirror::Class> declaring_class_;
+ HeapReference<mirror::Class> declaring_class_of_overridden_method_;
+ uint32_t access_flags_;
+ uint32_t dex_method_index_;
+
+ friend struct art::AbstractMethodOffsets; // for verifying offset information
+ DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod);
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index a300d5237e..5fc96ad961 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -36,7 +36,7 @@ namespace art {
namespace mirror {
inline uint32_t ArtMethod::ClassSize() {
- uint32_t vtable_entries = Object::kVTableLength + 7;
+ uint32_t vtable_entries = Object::kVTableLength;
return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
}
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 92aea1f3cc..9483ba6b4b 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -16,6 +16,7 @@
#include "art_method.h"
+#include "abstract_method.h"
#include "arch/context.h"
#include "art_field-inl.h"
#include "art_method-inl.h"
@@ -53,14 +54,11 @@ GcRoot<Class> ArtMethod::java_lang_reflect_ArtMethod_;
ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
jobject jlr_method) {
- ArtField* f =
- soa.DecodeField(WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
- mirror::ArtMethod* method = f->GetObject(soa.Decode<mirror::Object*>(jlr_method))->AsArtMethod();
- DCHECK(method != nullptr);
- return method;
+ auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(jlr_method);
+ DCHECK(abstract_method != nullptr);
+ return abstract_method->GetArtMethod();
}
-
void ArtMethod::VisitRoots(RootVisitor* visitor) {
java_lang_reflect_ArtMethod_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
}
@@ -547,5 +545,31 @@ void ArtMethod::UnregisterNative() {
RegisterNative(GetJniDlsymLookupStub(), false);
}
+bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
+ auto* dex_cache = GetDexCache();
+ auto* dex_file = dex_cache->GetDexFile();
+ const auto& method_id = dex_file->GetMethodId(GetDexMethodIndex());
+ const auto& proto_id = dex_file->GetMethodPrototype(method_id);
+ const DexFile::TypeList* proto_params = dex_file->GetProtoParameters(proto_id);
+ auto count = proto_params != nullptr ? proto_params->Size() : 0u;
+ auto param_len = params.Get() != nullptr ? params->GetLength() : 0u;
+ if (param_len != count) {
+ return false;
+ }
+ auto* cl = Runtime::Current()->GetClassLinker();
+ for (size_t i = 0; i < count; ++i) {
+ auto type_idx = proto_params->GetTypeItem(i).type_idx_;
+ auto* type = cl->ResolveType(type_idx, this);
+ if (type == nullptr) {
+ Thread::Current()->AssertPendingException();
+ return false;
+ }
+ if (type != params->GetWithoutChecks(i)) {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 55b8068d99..b899b25cc9 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -541,6 +541,10 @@ class MANAGED ArtMethod FINAL : public Object {
ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ // May cause thread suspension due to class resolution.
+ bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
static size_t SizeWithoutPointerFields(size_t pointer_size) {
size_t total = sizeof(ArtMethod) - sizeof(PtrSizedFields);
#ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 2afb4af0e3..1739019755 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -25,6 +25,7 @@
#include "dex_file-inl.h"
#include "gc/accounting/card_table-inl.h"
#include "handle_scope-inl.h"
+#include "method.h"
#include "object_array-inl.h"
#include "object-inl.h"
#include "runtime.h"
@@ -876,5 +877,26 @@ bool Class::ProxyDescriptorEquals(const char* match) {
return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
}
+mirror::ArtMethod* Class::GetDeclaredConstructor(
+ Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args) {
+ auto* direct_methods = GetDirectMethods();
+ size_t count = direct_methods != nullptr ? direct_methods->GetLength() : 0u;
+ for (size_t i = 0; i < count; ++i) {
+ auto* m = direct_methods->GetWithoutChecks(i);
+ // Skip <clinit> which is a static constructor, as well as non constructors.
+ if (m->IsStatic() || !m->IsConstructor()) {
+ continue;
+ }
+ // May cause thread suspension and exceptions.
+ if (m->EqualParameters(args)) {
+ return m;
+ }
+ if (self->IsExceptionPending()) {
+ return nullptr;
+ }
+ }
+ return nullptr;
+}
+
} // namespace mirror
} // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 20f23877e6..50053468db 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -47,6 +47,7 @@ namespace mirror {
class ArtMethod;
class ClassLoader;
+class Constructor;
class DexCache;
class IfTable;
@@ -1052,6 +1053,11 @@ class MANAGED Class FINAL : public Object {
return OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_strings_);
}
+ // May cause thread suspension due to EqualParameters.
+ mirror::ArtMethod* GetDeclaredConstructor(
+ Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
// Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore
// fence.
class InitializeClassVisitor {
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index 9988f84a72..d927f0c258 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -82,15 +82,12 @@ class MANAGED Field : public AccessibleObject {
}
static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
- static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
- static void VisitRoots(RootVisitor* visitor)
- SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+ static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
// Slow, try to use only for PrettyField and such.
ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
new file mode 100644
index 0000000000..81530bb130
--- /dev/null
+++ b/runtime/mirror/method.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "method.h"
+
+#include "mirror/art_method.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<Class> Method::static_class_;
+GcRoot<Class> Method::array_class_;
+GcRoot<Class> Constructor::static_class_;
+GcRoot<Class> Constructor::array_class_;
+
+void Method::SetClass(Class* klass) {
+ CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ static_class_ = GcRoot<Class>(klass);
+}
+
+void Method::ResetClass() {
+ CHECK(!static_class_.IsNull());
+ static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Method::SetArrayClass(Class* klass) {
+ CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ array_class_ = GcRoot<Class>(klass);
+}
+
+void Method::ResetArrayClass() {
+ CHECK(!array_class_.IsNull());
+ array_class_ = GcRoot<Class>(nullptr);
+}
+
+Method* Method::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+ DCHECK(!method->IsConstructor()) << PrettyMethod(method);
+ auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
+ if (LIKELY(ret != nullptr)) {
+ static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+ }
+ return ret;
+}
+
+void Method::VisitRoots(RootVisitor* visitor) {
+ static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+ array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+void Constructor::SetClass(Class* klass) {
+ CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ static_class_ = GcRoot<Class>(klass);
+}
+
+void Constructor::ResetClass() {
+ CHECK(!static_class_.IsNull());
+ static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Constructor::SetArrayClass(Class* klass) {
+ CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+ CHECK(klass != nullptr);
+ array_class_ = GcRoot<Class>(klass);
+}
+
+void Constructor::ResetArrayClass() {
+ CHECK(!array_class_.IsNull());
+ array_class_ = GcRoot<Class>(nullptr);
+}
+
+void Constructor::VisitRoots(RootVisitor* visitor) {
+ static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+ array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+Constructor* Constructor::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+ DCHECK(method->IsConstructor()) << PrettyMethod(method);
+ auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
+ if (LIKELY(ret != nullptr)) {
+ static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+ }
+ return ret;
+}
+
+} // namespace mirror
+} // namespace art
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
new file mode 100644
index 0000000000..88100f08e2
--- /dev/null
+++ b/runtime/mirror/method.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_H_
+#define ART_RUNTIME_MIRROR_METHOD_H_
+
+#include "abstract_method.h"
+#include "gc_root.h"
+
+namespace art {
+namespace mirror {
+
+class Class;
+
+// C++ mirror of java.lang.reflect.Method.
+class MANAGED Method : public AbstractMethod {
+ public:
+ static Method* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return static_class_.Read();
+ }
+
+ static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return array_class_.Read();
+ }
+
+ static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ static GcRoot<Class> static_class_; // java.lang.reflect.Method.class.
+ static GcRoot<Class> array_class_; // [java.lang.reflect.Method.class.
+
+ DISALLOW_COPY_AND_ASSIGN(Method);
+};
+
+// C++ mirror of java.lang.reflect.Constructor.
+class MANAGED Constructor: public AbstractMethod {
+ public:
+ static Constructor* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return static_class_.Read();
+ }
+
+ static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ return array_class_.Read();
+ }
+
+ static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+ static GcRoot<Class> static_class_; // java.lang.reflect.Constructor.class.
+ static GcRoot<Class> array_class_; // [java.lang.reflect.Constructor.class.
+
+ DISALLOW_COPY_AND_ASSIGN(Constructor);
+};
+
+} // namespace mirror
+} // namespace art
+
+#endif // ART_RUNTIME_MIRROR_METHOD_H_
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 5ad18f87ed..51a897d346 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -25,6 +25,7 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/field-inl.h"
+#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "mirror/object_array-inl.h"
#include "mirror/string-inl.h"
@@ -91,18 +92,6 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean
return soa.AddLocalReference<jclass>(c.Get());
}
-static jobject Class_findOverriddenMethodIfProxy(JNIEnv* env, jclass, jobject art_method) {
- ScopedFastNativeObjectAccess soa(env);
- mirror::ArtMethod* method = soa.Decode<mirror::ArtMethod*>(art_method);
- mirror::Class* declaring_klass = method->GetDeclaringClass();
- if (!declaring_klass->IsProxyClass()) {
- return art_method;
- }
- uint32_t dex_method_index = method->GetDexMethodIndex();
- mirror::ArtMethod* overriden_method = method->GetDexCacheResolvedMethods()->Get(dex_method_index);
- return soa.AddLocalReference<jobject>(overriden_method);
-}
-
static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
ScopedFastNativeObjectAccess soa(env);
StackHandleScope<1> hs(soa.Self());
@@ -252,7 +241,7 @@ static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jst
static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
ScopedFastNativeObjectAccess soa(env);
auto* name_string = soa.Decode<mirror::String*>(name);
- if (name == nullptr) {
+ if (name_string == nullptr) {
ThrowNullPointerException("name == null");
return nullptr;
}
@@ -269,17 +258,222 @@ static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring nam
return soa.AddLocalReference<jobject>(result);
}
+static jobject Class_getDeclaredConstructorInternal(
+ JNIEnv* env, jobject javaThis, jobjectArray args) {
+ ScopedFastNativeObjectAccess soa(env);
+ auto* klass = DecodeClass(soa, javaThis);
+ auto* params = soa.Decode<mirror::ObjectArray<mirror::Class>*>(args);
+ StackHandleScope<1> hs(soa.Self());
+ auto* declared_constructor = klass->GetDeclaredConstructor(soa.Self(), hs.NewHandle(params));
+ if (declared_constructor != nullptr) {
+ return soa.AddLocalReference<jobject>(
+ mirror::Constructor::CreateFromArtMethod(soa.Self(), declared_constructor));
+ }
+ return nullptr;
+}
+
+static ALWAYS_INLINE inline bool MethodMatchesConstructor(mirror::ArtMethod* m, bool public_only)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(m != nullptr);
+ return (!public_only || m->IsPublic()) && !m->IsStatic() && m->IsConstructor();
+}
+
+static jobjectArray Class_getDeclaredConstructorsInternal(
+ JNIEnv* env, jobject javaThis, jboolean publicOnly) {
+ ScopedFastNativeObjectAccess soa(env);
+ auto* klass = DecodeClass(soa, javaThis);
+ StackHandleScope<2> hs(soa.Self());
+ auto h_direct_methods = hs.NewHandle(klass->GetDirectMethods());
+ size_t constructor_count = 0;
+ auto count = h_direct_methods.Get() != nullptr ? h_direct_methods->GetLength() : 0u;
+ // Two pass approach for speed.
+ for (size_t i = 0; i < count; ++i) {
+ constructor_count += MethodMatchesConstructor(h_direct_methods->GetWithoutChecks(i),
+ publicOnly != JNI_FALSE) ? 1u : 0u;
+ }
+ auto h_constructors = hs.NewHandle(mirror::ObjectArray<mirror::Constructor>::Alloc(
+ soa.Self(), mirror::Constructor::ArrayClass(), constructor_count));
+ if (UNLIKELY(h_constructors.Get() == nullptr)) {
+ soa.Self()->AssertPendingException();
+ return nullptr;
+ }
+ constructor_count = 0;
+ for (size_t i = 0; i < count; ++i) {
+ auto* method = h_direct_methods->GetWithoutChecks(i);
+ if (MethodMatchesConstructor(method, publicOnly != JNI_FALSE)) {
+ auto* constructor = mirror::Constructor::CreateFromArtMethod(soa.Self(), method);
+ if (UNLIKELY(constructor == nullptr)) {
+ soa.Self()->AssertPendingException();
+ return nullptr;
+ }
+ h_constructors->SetWithoutChecks<false>(constructor_count++, constructor);
+ }
+ }
+ return soa.AddLocalReference<jobjectArray>(h_constructors.Get());
+}
+
+static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
+ jobject name, jobjectArray args) {
+ // Covariant return types permit the class to define multiple
+ // methods with the same name and parameter types. Prefer to
+ // return a non-synthetic method in such situations. We may
+ // still return a synthetic method to handle situations like
+ // escalated visibility. We never return miranda methods that
+ // were synthesized by the runtime.
+ constexpr uint32_t kSkipModifiers = kAccMiranda | kAccSynthetic;
+ ScopedFastNativeObjectAccess soa(env);
+ StackHandleScope<5> hs(soa.Self());
+ auto h_method_name = hs.NewHandle(soa.Decode<mirror::String*>(name));
+ if (UNLIKELY(h_method_name.Get() == nullptr)) {
+ ThrowNullPointerException("name == null");
+ return nullptr;
+ }
+ auto h_args = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
+ auto* klass = DecodeClass(soa, javaThis);
+ mirror::ArtMethod* result = nullptr;
+ auto* virtual_methods = klass->GetVirtualMethods();
+ if (virtual_methods != nullptr) {
+ auto h_virtual_methods = hs.NewHandle(virtual_methods);
+ for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
+ auto* m = h_virtual_methods->GetWithoutChecks(i);
+ auto* np_method = m->GetInterfaceMethodIfProxy();
+ // May cause thread suspension.
+ mirror::String* np_name = np_method->GetNameAsString(soa.Self());
+ if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+ if (UNLIKELY(soa.Self()->IsExceptionPending())) {
+ return nullptr;
+ }
+ continue;
+ }
+ auto modifiers = m->GetAccessFlags();
+ if ((modifiers & kSkipModifiers) == 0) {
+ return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), m));
+ }
+ if ((modifiers & kAccMiranda) == 0) {
+ result = m; // Remember as potential result if it's not a miranda method.
+ }
+ }
+ }
+ if (result == nullptr) {
+ auto* direct_methods = klass->GetDirectMethods();
+ if (direct_methods != nullptr) {
+ auto h_direct_methods = hs.NewHandle(direct_methods);
+ for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
+ auto* m = h_direct_methods->GetWithoutChecks(i);
+ auto modifiers = m->GetAccessFlags();
+ if ((modifiers & kAccConstructor) != 0) {
+ continue;
+ }
+ auto* np_method = m->GetInterfaceMethodIfProxy();
+ // May cause thread suspension.
+ mirror::String* np_name = np_method ->GetNameAsString(soa.Self());
+ if (np_name == nullptr) {
+ soa.Self()->AssertPendingException();
+ return nullptr;
+ }
+ if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
+ if (UNLIKELY(soa.Self()->IsExceptionPending())) {
+ return nullptr;
+ }
+ continue;
+ }
+ if ((modifiers & kSkipModifiers) == 0) {
+ return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(
+ soa.Self(), m));
+ }
+ // Direct methods cannot be miranda methods, so this potential result must be synthetic.
+ result = m;
+ }
+ }
+ }
+ return result != nullptr ?
+ soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), result)) :
+ nullptr;
+}
+
+jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis,
+ jboolean publicOnly) {
+ ScopedFastNativeObjectAccess soa(env);
+ StackHandleScope<5> hs(soa.Self());
+ auto* klass = DecodeClass(soa, javaThis);
+ auto virtual_methods = hs.NewHandle(klass->GetVirtualMethods());
+ auto direct_methods = hs.NewHandle(klass->GetDirectMethods());
+ size_t num_methods = 0;
+ if (virtual_methods.Get() != nullptr) {
+ for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
+ auto* m = virtual_methods->GetWithoutChecks(i);
+ auto modifiers = m->GetAccessFlags();
+ if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+ (modifiers & kAccMiranda) == 0) {
+ ++num_methods;
+ }
+ }
+ }
+ if (direct_methods.Get() != nullptr) {
+ for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
+ auto* m = direct_methods->GetWithoutChecks(i);
+ auto modifiers = m->GetAccessFlags();
+ // Add non-constructor direct/static methods.
+ if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+ (modifiers & kAccConstructor) == 0) {
+ ++num_methods;
+ }
+ }
+ }
+ auto ret = hs.NewHandle(mirror::ObjectArray<mirror::Method>::Alloc(
+ soa.Self(), mirror::Method::ArrayClass(), num_methods));
+ num_methods = 0;
+ if (virtual_methods.Get() != nullptr) {
+ for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
+ auto* m = virtual_methods->GetWithoutChecks(i);
+ auto modifiers = m->GetAccessFlags();
+ if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+ (modifiers & kAccMiranda) == 0) {
+ auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
+ if (method == nullptr) {
+ soa.Self()->AssertPendingException();
+ return nullptr;
+ }
+ ret->SetWithoutChecks<false>(num_methods++, method);
+ }
+ }
+ }
+ if (direct_methods.Get() != nullptr) {
+ for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
+ auto* m = direct_methods->GetWithoutChecks(i);
+ auto modifiers = m->GetAccessFlags();
+ // Add non-constructor direct/static methods.
+ if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
+ (modifiers & kAccConstructor) == 0) {
+ auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
+ if (method == nullptr) {
+ soa.Self()->AssertPendingException();
+ return nullptr;
+ }
+ ret->SetWithoutChecks<false>(num_methods++, method);
+ }
+ }
+ }
+ return soa.AddLocalReference<jobjectArray>(ret.Get());
+}
+
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
- NATIVE_METHOD(Class, findOverriddenMethodIfProxy,
- "!(Ljava/lang/reflect/ArtMethod;)Ljava/lang/reflect/ArtMethod;"),
+ NATIVE_METHOD(Class, classForName,
+ "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
+ NATIVE_METHOD(Class, getDeclaredConstructorInternal,
+ "!([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"),
+ NATIVE_METHOD(Class, getDeclaredConstructorsInternal, "!(Z)[Ljava/lang/reflect/Constructor;"),
+ NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
+ NATIVE_METHOD(Class, getDeclaredMethodInternal,
+ "!(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"),
+ NATIVE_METHOD(Class, getDeclaredMethodsUnchecked,
+ "!(Z)[Ljava/lang/reflect/Method;"),
NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
- NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
- NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
- NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
- NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
};
void register_java_lang_Class(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Constructor.cc b/runtime/native/java_lang_reflect_Constructor.cc
index 5e1a4c59f7..c33f81a211 100644
--- a/runtime/native/java_lang_reflect_Constructor.cc
+++ b/runtime/native/java_lang_reflect_Constructor.cc
@@ -21,6 +21,7 @@
#include "mirror/art_method.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
+#include "mirror/method.h"
#include "mirror/object-inl.h"
#include "reflection.h"
#include "scoped_fast_native_object_access.h"
@@ -28,17 +29,10 @@
namespace art {
-/*
- * We get here through Constructor.newInstance(). The Constructor object
- * would not be available if the constructor weren't public (per the
- * definition of Class.getConstructor), so we can skip the method access
- * check. We can also safely assume the constructor isn't associated
- * with an interface, array, or primitive class.
- */
-static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs,
- jboolean accessible) {
+static ALWAYS_INLINE inline jobject NewInstanceHelper(
+ JNIEnv* env, jobject javaMethod, jobjectArray javaArgs, size_t num_frames) {
ScopedFastNativeObjectAccess soa(env);
- mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
+ mirror::Method* m = soa.Decode<mirror::Method*>(javaMethod);
StackHandleScope<1> hs(soa.Self());
Handle<mirror::Class> c(hs.NewHandle(m->GetDeclaringClass()));
if (UNLIKELY(c->IsAbstract())) {
@@ -67,14 +61,31 @@ static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectA
}
jobject javaReceiver = soa.AddLocalReference<jobject>(receiver);
- InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, (accessible == JNI_TRUE));
+ InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, num_frames);
// Constructors are ()V methods, so we shouldn't touch the result of InvokeMethod.
return javaReceiver;
}
+/*
+ * We get here through Constructor.newInstance(). The Constructor object
+ * would not be available if the constructor weren't public (per the
+ * definition of Class.getConstructor), so we can skip the method access
+ * check. We can also safely assume the constructor isn't associated
+ * with an interface, array, or primitive class.
+ */
+static jobject Constructor_newInstance(JNIEnv* env, jobject javaMethod, jobjectArray javaArgs) {
+ return NewInstanceHelper(env, javaMethod, javaArgs, 1);
+}
+
+static jobject Constructor_newInstanceTwoFrames(JNIEnv* env, jobject javaMethod,
+ jobjectArray javaArgs) {
+ return NewInstanceHelper(env, javaMethod, javaArgs, 2);
+}
+
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;Z)Ljava/lang/Object;"),
+ NATIVE_METHOD(Constructor, newInstance, "!([Ljava/lang/Object;)Ljava/lang/Object;"),
+ NATIVE_METHOD(Constructor, newInstanceTwoFrames, "!([Ljava/lang/Object;)Ljava/lang/Object;"),
};
void register_java_lang_reflect_Constructor(JNIEnv* env) {
diff --git a/runtime/native/java_lang_reflect_Method.cc b/runtime/native/java_lang_reflect_Method.cc
index 9859746563..c20d83245c 100644
--- a/runtime/native/java_lang_reflect_Method.cc
+++ b/runtime/native/java_lang_reflect_Method.cc
@@ -30,9 +30,9 @@
namespace art {
static jobject Method_invoke(JNIEnv* env, jobject javaMethod, jobject javaReceiver,
- jobject javaArgs, jboolean accessible) {
+ jobject javaArgs) {
ScopedFastNativeObjectAccess soa(env);
- return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs, (accessible == JNI_TRUE));
+ return InvokeMethod(soa, javaMethod, javaReceiver, javaArgs);
}
static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
@@ -55,7 +55,7 @@ static jobject Method_getExceptionTypesNative(JNIEnv* env, jobject javaMethod) {
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;Z)Ljava/lang/Object;"),
+ NATIVE_METHOD(Method, invoke, "!(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;"),
NATIVE_METHOD(Method, getExceptionTypesNative, "!()[Ljava/lang/Class;"),
};
diff --git a/runtime/native/java_lang_reflect_Proxy.cc b/runtime/native/java_lang_reflect_Proxy.cc
index baf8b24207..4a6ab404f2 100644
--- a/runtime/native/java_lang_reflect_Proxy.cc
+++ b/runtime/native/java_lang_reflect_Proxy.cc
@@ -30,13 +30,12 @@ static jclass Proxy_generateProxy(JNIEnv* env, jclass, jstring name, jobjectArra
jobject loader, jobjectArray methods, jobjectArray throws) {
ScopedFastNativeObjectAccess soa(env);
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
- mirror::Class* result = class_linker->CreateProxyClass(soa, name, interfaces, loader, methods,
- throws);
- return soa.AddLocalReference<jclass>(result);
+ return soa.AddLocalReference<jclass>(class_linker->CreateProxyClass(
+ soa, name, interfaces, loader, methods, throws));
}
static JNINativeMethod gMethods[] = {
- NATIVE_METHOD(Proxy, generateProxy, "!(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/ArtMethod;[[Ljava/lang/Class;)Ljava/lang/Class;"),
+ NATIVE_METHOD(Proxy, generateProxy, "!(Ljava/lang/String;[Ljava/lang/Class;Ljava/lang/ClassLoader;[Ljava/lang/reflect/Method;[[Ljava/lang/Class;)Ljava/lang/Class;"),
};
void register_java_lang_reflect_Proxy(JNIEnv* env) {
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 6061f73c19..b471293c09 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -20,6 +20,7 @@
#include "art_field-inl.h"
#include "class_linker-inl.h"
#include "common_compiler_test.h"
+#include "mirror/method.h"
#include "scoped_thread_state_change.h"
namespace art {
@@ -53,41 +54,34 @@ class ProxyTest : public CommonCompilerTest {
mirror::ObjectArray<mirror::ArtMethod>* virtual_methods = interface->GetVirtualMethods();
methods_count += (virtual_methods == nullptr) ? 0 : virtual_methods->GetLength();
}
- jclass javaLangReflectArtMethod =
- soa.AddLocalReference<jclass>(mirror::ArtMethod::GetJavaLangReflectArtMethod());
- jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(methods_count,
- javaLangReflectArtMethod, nullptr);
+ jobjectArray proxyClassMethods = soa.Env()->NewObjectArray(
+ methods_count, soa.AddLocalReference<jclass>(mirror::Method::StaticClass()), nullptr);
soa.Self()->AssertNoPendingException();
- // Fill the method array
- mirror::ArtMethod* equalsMethod = javaLangObject->FindDeclaredVirtualMethod("equals",
- "(Ljava/lang/Object;)Z");
- mirror::ArtMethod* hashCodeMethod = javaLangObject->FindDeclaredVirtualMethod("hashCode",
- "()I");
- mirror::ArtMethod* toStringMethod = javaLangObject->FindDeclaredVirtualMethod("toString",
- "()Ljava/lang/String;");
- CHECK(equalsMethod != nullptr);
- CHECK(hashCodeMethod != nullptr);
- CHECK(toStringMethod != nullptr);
-
jsize array_index = 0;
- // Adds Object methods.
- soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
- soa.AddLocalReference<jobject>(equalsMethod));
- soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
- soa.AddLocalReference<jobject>(hashCodeMethod));
- soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
- soa.AddLocalReference<jobject>(toStringMethod));
-
+ // Fill the method array
+ mirror::ArtMethod* method = javaLangObject->FindDeclaredVirtualMethod(
+ "equals", "(Ljava/lang/Object;)Z");
+ CHECK(method != nullptr);
+ soa.Env()->SetObjectArrayElement(
+ proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+ mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+ method = javaLangObject->FindDeclaredVirtualMethod("hashCode", "()I");
+ CHECK(method != nullptr);
+ soa.Env()->SetObjectArrayElement(
+ proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+ mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+ method = javaLangObject->FindDeclaredVirtualMethod("toString", "()Ljava/lang/String;");
+ CHECK(method != nullptr);
+ soa.Env()->SetObjectArrayElement(
+ proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+ mirror::Method::CreateFromArtMethod(soa.Self(), method)));
// Now adds all interfaces virtual methods.
for (mirror::Class* interface : interfaces) {
- mirror::ObjectArray<mirror::ArtMethod>* virtual_methods = interface->GetVirtualMethods();
- if (virtual_methods != nullptr) {
- for (int32_t mth_index = 0; mth_index < virtual_methods->GetLength(); ++mth_index) {
- mirror::ArtMethod* method = virtual_methods->Get(mth_index);
- soa.Env()->SetObjectArrayElement(proxyClassMethods, array_index++,
- soa.AddLocalReference<jobject>(method));
- }
+ for (int32_t i = 0, count = interface->NumVirtualMethods(); i < count; ++i) {
+ soa.Env()->SetObjectArrayElement(
+ proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
+ mirror::Method::CreateFromArtMethod(soa.Self(), interface->GetVirtualMethod(i))));
}
}
CHECK_EQ(array_index, methods_count);
@@ -96,10 +90,9 @@ class ProxyTest : public CommonCompilerTest {
jobjectArray proxyClassThrows = soa.Env()->NewObjectArray(0, javaLangClass, nullptr);
soa.Self()->AssertNoPendingException();
- mirror::Class* proxyClass = class_linker_->CreateProxyClass(soa,
- soa.Env()->NewStringUTF(className),
- proxyClassInterfaces, jclass_loader,
- proxyClassMethods, proxyClassThrows);
+ mirror::Class* proxyClass = class_linker_->CreateProxyClass(
+ soa, soa.Env()->NewStringUTF(className), proxyClassInterfaces, jclass_loader,
+ proxyClassMethods, proxyClassThrows);
soa.Self()->AssertNoPendingException();
return proxyClass;
}
diff --git a/runtime/reflection.cc b/runtime/reflection.cc
index 3e1315c73e..e54673831f 100644
--- a/runtime/reflection.cc
+++ b/runtime/reflection.cc
@@ -22,6 +22,7 @@
#include "dex_file-inl.h"
#include "entrypoints/entrypoint_utils.h"
#include "jni_internal.h"
+#include "mirror/abstract_method.h"
#include "mirror/art_method-inl.h"
#include "mirror/class-inl.h"
#include "mirror/object_array-inl.h"
@@ -537,7 +538,7 @@ void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg
}
jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod,
- jobject javaReceiver, jobject javaArgs, bool accessible) {
+ jobject javaReceiver, jobject javaArgs, size_t num_frames) {
// We want to make sure that the stack is not within a small distance from the
// protected region in case we are calling into a leaf function whose stack
// check has been elided.
@@ -547,7 +548,9 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
return nullptr;
}
- mirror::ArtMethod* m = mirror::ArtMethod::FromReflectedMethod(soa, javaMethod);
+ auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(javaMethod);
+ const bool accessible = abstract_method->IsAccessible();
+ mirror::ArtMethod* m = abstract_method->GetArtMethod();
mirror::Class* declaring_class = m->GetDeclaringClass();
if (UNLIKELY(!declaring_class->IsInitialized())) {
@@ -572,8 +575,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
}
// Get our arrays of arguments and their types, and check they're the same size.
- mirror::ObjectArray<mirror::Object>* objects =
- soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
+ auto* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs);
const DexFile::TypeList* classes = m->GetParameterTypeList();
uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size();
uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0;
@@ -586,7 +588,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM
// If method is not set to be accessible, verify it can be accessed by the caller.
mirror::Class* calling_class = nullptr;
if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags(),
- &calling_class, 2)) {
+ &calling_class, num_frames)) {
ThrowIllegalAccessException(
StringPrintf("Class %s cannot access %s method %s of class %s",
calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(),
diff --git a/runtime/reflection.h b/runtime/reflection.h
index c2d406a2db..c63f858129 100644
--- a/runtime/reflection.h
+++ b/runtime/reflection.h
@@ -65,8 +65,9 @@ void InvokeWithShadowFrame(Thread* self, ShadowFrame* shadow_frame, uint16_t arg
JValue* result)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+// num_frames is number of frames we look up for access check.
jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject method, jobject receiver,
- jobject args, bool accessible)
+ jobject args, size_t num_frames = 1)
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
ALWAYS_INLINE bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c)
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 7bebb965f4..2fc8d2045d 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -77,6 +77,7 @@
#include "mirror/class-inl.h"
#include "mirror/class_loader.h"
#include "mirror/field.h"
+#include "mirror/method.h"
#include "mirror/stack_trace_element.h"
#include "mirror/throwable.h"
#include "monitor.h"
@@ -1308,7 +1309,9 @@ void Runtime::VisitConstantRoots(RootVisitor* visitor) {
// need to be visited once per GC since they never change.
mirror::ArtMethod::VisitRoots(visitor);
mirror::Class::VisitRoots(visitor);
+ mirror::Constructor::VisitRoots(visitor);
mirror::Reference::VisitRoots(visitor);
+ mirror::Method::VisitRoots(visitor);
mirror::StackTraceElement::VisitRoots(visitor);
mirror::String::VisitRoots(visitor);
mirror::Throwable::VisitRoots(visitor);
diff --git a/runtime/well_known_classes.cc b/runtime/well_known_classes.cc
index d389244f47..f57f9c485d 100644
--- a/runtime/well_known_classes.cc
+++ b/runtime/well_known_classes.cc
@@ -212,7 +212,7 @@ void WellKnownClasses::Init(JNIEnv* env) {
ScopedLocalRef<jclass> java_lang_ref_ReferenceQueue(env, env->FindClass("java/lang/ref/ReferenceQueue"));
java_lang_ref_ReferenceQueue_add = CacheMethod(env, java_lang_ref_ReferenceQueue.get(), true, "add", "(Ljava/lang/ref/Reference;)V");
- java_lang_reflect_Proxy_invoke = CacheMethod(env, java_lang_reflect_Proxy, true, "invoke", "(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/ArtMethod;[Ljava/lang/Object;)Ljava/lang/Object;");
+ java_lang_reflect_Proxy_invoke = CacheMethod(env, java_lang_reflect_Proxy, true, "invoke", "(Ljava/lang/reflect/Proxy;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;");
java_lang_Thread_init = CacheMethod(env, java_lang_Thread, false, "<init>", "(Ljava/lang/ThreadGroup;Ljava/lang/String;IZ)V");
java_lang_Thread_run = CacheMethod(env, java_lang_Thread, false, "run", "()V");
java_lang_Thread__UncaughtExceptionHandler_uncaughtException = CacheMethod(env, java_lang_Thread__UncaughtExceptionHandler, false, "uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");