Use explicit list of mirrored class when checking CanRedefine
We were assuming that the ClassRoots contained all the mirror'd
classes but this is not the case. Instead we should use an explicit
list of the mirror'd classes.
Test: ./test.py --host
Test: m test-art-host-gtest-class_linker_test64
Bug: 134162467
Change-Id: Idd4c258ee0134e42afd0175b948123ea052704e1
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 6299e3f..0969b1c 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -479,6 +479,7 @@
ObjPtr<mirror::Class> klass =
Runtime::Current()->GetClassLinker()->FindSystemClass(self, class_descriptor.c_str());
CHECK(klass != nullptr) << class_descriptor;
+ CHECK(klass->IsMirrored()) << class_descriptor;
bool error = false;
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index e1dd54f..834b857 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -16,6 +16,9 @@
#include "class.h"
+#include <unordered_set>
+#include <string_view>
+
#include "android-base/macros.h"
#include "android-base/stringprintf.h"
@@ -62,6 +65,49 @@
using android::base::StringPrintf;
+bool Class::IsMirrored() {
+ if (LIKELY(!IsBootStrapClassLoaded())) {
+ return false;
+ }
+ if (IsPrimitive() || IsArrayClass() || IsProxyClass()) {
+ return true;
+ }
+ // TODO Have this list automatically populated.
+ std::unordered_set<std::string_view> mirror_types = {
+ "Ljava/lang/Class;",
+ "Ljava/lang/ClassLoader;",
+ "Ljava/lang/ClassNotFoundException;",
+ "Ljava/lang/DexCache;",
+ "Ljava/lang/Object;",
+ "Ljava/lang/StackTraceElement;",
+ "Ljava/lang/String;",
+ "Ljava/lang/Throwable;",
+ "Ljava/lang/invoke/ArrayElementVarHandle;",
+ "Ljava/lang/invoke/ByteArrayViewVarHandle;",
+ "Ljava/lang/invoke/ByteBufferViewVarHandle;",
+ "Ljava/lang/invoke/CallSite;",
+ "Ljava/lang/invoke/FieldVarHandle;",
+ "Ljava/lang/invoke/MethodHandle;",
+ "Ljava/lang/invoke/MethodHandleImpl;",
+ "Ljava/lang/invoke/MethodHandles$Lookup;",
+ "Ljava/lang/invoke/MethodType;",
+ "Ljava/lang/invoke/VarHandle;",
+ "Ljava/lang/ref/FinalizerReference;",
+ "Ljava/lang/ref/Reference;",
+ "Ljava/lang/reflect/AccessibleObject;",
+ "Ljava/lang/reflect/Constructor;",
+ "Ljava/lang/reflect/Executable;",
+ "Ljava/lang/reflect/Field;",
+ "Ljava/lang/reflect/Method;",
+ "Ljava/lang/reflect/Proxy;",
+ "Ldalvik/system/ClassExt;",
+ "Ldalvik/system/EmulatedStackFrame;",
+ };
+ std::string name_storage;
+ const std::string name(this->GetDescriptor(&name_storage));
+ return mirror_types.find(name) != mirror_types.end();
+}
+
ObjPtr<mirror::Class> Class::GetPrimitiveClass(ObjPtr<mirror::String> name) {
const char* expected_name = nullptr;
ClassRoot class_root = ClassRoot::kJavaLangObject; // Invalid.
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 15f7dc6..b1186d9 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -191,6 +191,9 @@
return status == ClassStatus::kVisiblyInitialized;
}
+ // Returns true if this class is ever accessed through a C++ mirror.
+ bool IsMirrored() REQUIRES_SHARED(Locks::mutator_lock_);
+
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE uint32_t GetAccessFlags() REQUIRES_SHARED(Locks::mutator_lock_) {
if (kIsDebugBuild) {