Setup Thread's context ClassLoader and add image DexFiles to ClassLinker's boot classpath
Change-Id: I84337c69ff743c58be9e7125d17fcccb514614ef
diff --git a/Android.mk b/Android.mk
index 9a53fd0..7008326 100644
--- a/Android.mk
+++ b/Android.mk
@@ -134,7 +134,7 @@
test-art-target-oat-process-am: $(TARGET_OUT_JAVA_LIBRARIES)/am.oat test-art-target-sync
adb remount
adb sync
- adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art -Ximage:/system/framework/am.art /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am"
+ adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am"
$(hide) (adb pull /sdcard/test-art-target-process-am /tmp/ && echo test-art-target-process-am PASSED) || echo test-art-target-process-am FAILED
$(hide) rm /tmp/test-art-target-process-am
@@ -158,7 +158,7 @@
sleep 30; \
fi
adb shell kill `adb shell ps | fgrep com.android.calculator2 | sed -e 's/[^ ]* *\([0-9]*\).*/\1/'`
- adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art -Ximage:/system/framework/am.art /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator"
+ adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Ximage:/system/framework/boot.art /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator"
$(hide) (adb pull /sdcard/test-art-target-process-Calculator /tmp/ && echo test-art-target-process-Calculator PASSED) || echo test-art-target-process-Calculator FAILED
$(hide) rm /tmp/test-art-target-process-Calculator
diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp
index 53321f1..4e90dab 100644
--- a/oat_process/app_main.cpp
+++ b/oat_process/app_main.cpp
@@ -77,7 +77,7 @@
char* slashClassName = toSlashClassName(mClassName);
mClass = env->FindClass(slashClassName);
if (mClass == NULL) {
- LOG(ERROR) << StringPrintf("ERROR: could not find class '%s'\n", mClassName);
+ LOG(FATAL) << "Could not find class: " << mClassName;
}
free(slashClassName);
diff --git a/src/class_linker.cc b/src/class_linker.cc
index 5159f06..97a75ac 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -633,7 +633,7 @@
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file_location);
CHECK_EQ(dex_file->GetHeader().checksum_, oat_dex_file->GetDexFileChecksum());
- RegisterDexFile(*dex_file, dex_cache);
+ AppendToBootClassPath(*dex_file, dex_cache);
}
}
}
@@ -852,22 +852,18 @@
std::string class_name_string = DescriptorToDot(descriptor);
ScopedThreadStateChange(self, Thread::kNative);
JNIEnv* env = self->GetJniEnv();
- jclass c = AddLocalReference<jclass>(env, GetClassRoot(kJavaLangClassLoader));
- CHECK(c != NULL);
+ ScopedLocalRef<jclass> c(env, AddLocalReference<jclass>(env, GetClassRoot(kJavaLangClassLoader)));
+ CHECK(c.get() != NULL);
// TODO: cache method?
- jmethodID mid = env->GetMethodID(c, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
+ jmethodID mid = env->GetMethodID(c.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
CHECK(mid != NULL);
- jobject class_name_object = env->NewStringUTF(class_name_string.c_str());
+ ScopedLocalRef<jobject> class_name_object(env, env->NewStringUTF(class_name_string.c_str()));
if (class_name_string == NULL) {
return NULL;
}
- jobject class_loader_object = AddLocalReference<jobject>(env, class_loader);
- jobject result = env->CallObjectMethod(class_loader_object, mid, class_name_object);
- Class* klass_result = Decode<Class*>(env, result);
- env->DeleteLocalRef(result);
- env->DeleteLocalRef(class_name_object);
- env->DeleteLocalRef(c);
- return klass_result;
+ ScopedLocalRef<jobject> class_loader_object(env, AddLocalReference<jobject>(env, class_loader));
+ ScopedLocalRef<jobject> result(env, env->CallObjectMethod(class_loader_object.get(), mid, class_name_object.get()));
+ return Decode<Class*>(env, result.get());
}
Class* ClassLinker::DefineClass(const std::string& descriptor,
@@ -1608,9 +1604,8 @@
if (klass->IsErroneous()) {
// The caller wants an exception, but it was thrown in a
// different thread. Synthesize one here.
- self->ThrowNewExceptionF("Ljava/lang/NoClassDefFoundError;",
- "<clinit> failed for class %s; see exception in other thread",
- PrettyDescriptor(klass->GetDescriptor()).c_str());
+ ThrowNoClassDefFoundError("<clinit> failed for class %s; see exception in other thread",
+ PrettyDescriptor(klass->GetDescriptor()).c_str());
return false;
}
if (klass->IsInitialized()) {
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index 5905642..96b7817 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -117,12 +117,15 @@
if (dex_file == NULL) {
return NULL;
}
- String* name = Decode<String*>(env, javaName);
- const char* class_name = name->ToModifiedUtf8().c_str();
- const std::string descriptor = DotToDescriptor(class_name);
+ ScopedUtfChars class_name(env, javaName);
+ if (class_name.c_str() == NULL) {
+ return NULL;
+ }
+ const std::string descriptor = DotToDescriptor(class_name.c_str());
const DexFile::ClassDef* dex_class_def = dex_file->FindClassDef(descriptor);
if (dex_class_def == NULL) {
- jniThrowExceptionFmt(env, "java/lang/NoClassDefFoundError", "Class %s not found", class_name);
+ jniThrowExceptionFmt(env, "java/lang/NoClassDefFoundError", "Class %s not found",
+ class_name.c_str());
return NULL;
}
diff --git a/src/runtime.cc b/src/runtime.cc
index c733bfe..b4c25d3 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -320,16 +320,17 @@
CHECK_EQ(self->GetState(), Thread::kNative);
JNIEnv* env = self->GetJniEnv();
- ScopedLocalRef<jclass> c(env, env->FindClass("java/lang/ClassLoader"));
- CHECK(c.get() != NULL);
- jmethodID mid = env->GetStaticMethodID(c.get(),
- "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
- CHECK(mid != NULL);
- ScopedLocalRef<jobject> result(env, env->CallStaticObjectMethod(c.get(), mid));
- CHECK(result.get() != NULL);
+ ScopedLocalRef<jclass> ClassLoader_class(env, env->FindClass("java/lang/ClassLoader"));
+ CHECK(ClassLoader_class.get() != NULL);
+ jmethodID getSystemClassLoader = env->GetStaticMethodID(ClassLoader_class.get(),
+ "getSystemClassLoader",
+ "()Ljava/lang/ClassLoader;");
+ CHECK(getSystemClassLoader != NULL);
+ ScopedLocalRef<jobject> class_loader(env, env->CallStaticObjectMethod(ClassLoader_class.get(),
+ getSystemClassLoader));
+ CHECK(class_loader.get() != NULL);
- ClassLoader* class_loader = Decode<ClassLoader*>(env, result.get());
- Thread::Current()->SetClassLoaderOverride(class_loader);
+ Thread::Current()->SetClassLoaderOverride(Decode<ClassLoader*>(env, class_loader.get()));
}
void Runtime::Start() {
diff --git a/src/thread.cc b/src/thread.cc
index 4dcef55..d9c6b4f 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -27,6 +27,7 @@
#include <list>
#include "class_linker.h"
+#include "class_loader.h"
#include "context.h"
#include "dex_verifier.h"
#include "heap.h"
@@ -631,6 +632,7 @@
Class* boolean_class = FindPrimitiveClassOrDie(class_linker, 'Z');
Class* int_class = FindPrimitiveClassOrDie(class_linker, 'I');
+ Class* ClassLoader_class = FindClassOrDie(class_linker, "Ljava/lang/ClassLoader;");
Class* String_class = FindClassOrDie(class_linker, "Ljava/lang/String;");
Class* Thread_class = FindClassOrDie(class_linker, "Ljava/lang/Thread;");
Class* ThreadGroup_class = FindClassOrDie(class_linker, "Ljava/lang/ThreadGroup;");
@@ -654,7 +656,11 @@
"uncaughtException", "(Ljava/lang/Thread;Ljava/lang/Throwable;)V");
// Finish attaching the main thread.
- Thread::Current()->CreatePeer("main", false);
+ Thread* self = Thread::Current();
+ self->CreatePeer("main", false);
+
+ const Field* Thread_contextClassLoader = FindFieldOrDie(Thread_class , "contextClassLoader", ClassLoader_class);
+ Thread_contextClassLoader->SetObject(self->GetPeer(), self->GetClassLoaderOverride());
}
void Thread::Shutdown() {