summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_common.cc
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2013-12-09 13:51:32 -0800
committerKenny Root <kroot@google.com>2013-12-09 14:27:36 -0800
commitfa31b3c382f5202bc2b07c81108627e476cf753d (patch)
treedd186725570664f8c263fc06fc47c0488a3005ae /runtime/interpreter/interpreter_common.cc
parent400455c23d6a9a849d090b9e60ff53c4422e461b (diff)
downloadart-fa31b3c382f5202bc2b07c81108627e476cf753d.zip
art-fa31b3c382f5202bc2b07c81108627e476cf753d.tar.gz
art-fa31b3c382f5202bc2b07c81108627e476cf753d.tar.bz2
Add some functions to the unitialized VM handling
Only the Class#forName(String) call was handled during the compilation stage, but VMClassLoader#loadClass and VMClassLoader#findLoadedClass gets called through various other channels. Add these so we cover most of the use cases without going too far up the call stack. This was encountered during compilation of code that did: MyClass.class.getClassLoader().loadClass(...) during an attempt to avoid class initialization. Note that the existing Class#forName handling doesn't appear to ensure the class is initialized like would normally happen when Class#forName is called in the running VM. This is a correctness issue, but is left for another change to correct. Change-Id: I14628a1d1d5a5dd1a885cbd24455a73bb0531489
Diffstat (limited to 'runtime/interpreter/interpreter_common.cc')
-rw-r--r--runtime/interpreter/interpreter_common.cc12
1 files changed, 11 insertions, 1 deletions
diff --git a/runtime/interpreter/interpreter_common.cc b/runtime/interpreter/interpreter_common.cc
index c9756ac..ca066b6 100644
--- a/runtime/interpreter/interpreter_common.cc
+++ b/runtime/interpreter/interpreter_common.cc
@@ -231,7 +231,10 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
// In a runtime that's not started we intercept certain methods to avoid complicated dependency
// problems in core libraries.
std::string name(PrettyMethod(shadow_frame->GetMethod()));
- if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)") {
+ if (name == "java.lang.Class java.lang.Class.forName(java.lang.String)"
+ || name == "java.lang.Class java.lang.VMClassLoader.loadClass(java.lang.String, boolean)") {
+ // TODO Class#forName should actually call Class::EnsureInitialized always. Support for the
+ // other variants that take more arguments should also be added.
std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset)->AsString()->ToModifiedUtf8().c_str()));
SirtRef<ClassLoader> class_loader(self, nullptr); // shadow_frame.GetMethod()->GetDeclaringClass()->GetClassLoader();
@@ -240,6 +243,13 @@ static void UnstartedRuntimeInvoke(Thread* self, MethodHelper& mh,
CHECK(found != NULL) << "Class.forName failed in un-started runtime for class: "
<< PrettyDescriptor(descriptor);
result->SetL(found);
+ } else if (name == "java.lang.Class java.lang.VMClassLoader.findLoadedClass(java.lang.ClassLoader, java.lang.String)") {
+ SirtRef<ClassLoader> class_loader(self, down_cast<mirror::ClassLoader*>(shadow_frame->GetVRegReference(arg_offset)));
+ std::string descriptor(DotToDescriptor(shadow_frame->GetVRegReference(arg_offset + 1)->AsString()->ToModifiedUtf8().c_str()));
+
+ Class* found = Runtime::Current()->GetClassLinker()->FindClass(descriptor.c_str(),
+ class_loader);
+ result->SetL(found);
} else if (name == "java.lang.Object java.lang.Class.newInstance()") {
Class* klass = shadow_frame->GetVRegReference(arg_offset)->AsClass();
ArtMethod* c = klass->FindDeclaredDirectMethod("<init>", "()V");