Improved ClassLoader support for JNI FindClass, FieldFieldID, JNI_OnLoad
Also fix AttachCurrentThread to use the peer's thread name,
not the possibly null name from the arguments.
Change-Id: I12e612619d828734d8353a0dca44fb4f11ee0c66
diff --git a/src/jni_internal.cc b/src/jni_internal.cc
index 0982f83..5052773 100644
--- a/src/jni_internal.cc
+++ b/src/jni_internal.cc
@@ -310,6 +310,15 @@
return EncodeMethod(method);
}
+const ClassLoader* GetClassLoader(Thread* self) {
+ Frame frame = self->GetTopOfStack();
+ Method* method = frame.GetMethod();
+ if (method == NULL || PrettyMethod(method, false) == "java.lang.Runtime.nativeLoad") {
+ return self->GetClassLoaderOverride();
+ }
+ return method->GetDeclaringClass()->GetClassLoader();
+}
+
jfieldID FindFieldID(ScopedJniThreadState& ts, jclass jni_class, const char* name, const char* sig, bool is_static) {
Class* c = Decode<Class*>(ts, jni_class);
if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(c, true)) {
@@ -320,8 +329,7 @@
Class* field_type;
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
if (sig[1] != '\0') {
- // TODO: need to get the appropriate ClassLoader.
- const ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
+ const ClassLoader* cl = GetClassLoader(ts.Self());
field_type = class_linker->FindClass(sig, cl);
} else {
field_type = class_linker->FindPrimitiveClass(*sig);
@@ -641,8 +649,7 @@
std::string descriptor(NormalizeJniClassDescriptor(name));
Class* c = NULL;
if (runtime->IsStarted()) {
- // TODO: need to get the appropriate ClassLoader.
- const ClassLoader* cl = ts.Self()->GetClassLoaderOverride();
+ const ClassLoader* cl = GetClassLoader(ts.Self());
c = class_linker->FindClass(descriptor, cl);
} else {
c = class_linker->FindSystemClass(descriptor);
diff --git a/src/thread.cc b/src/thread.cc
index 6fdeefd..54d2e6c 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -164,10 +164,8 @@
{
CHECK_EQ(self->GetState(), Thread::kRunnable);
- String* thread_name = reinterpret_cast<String*>(gThread_name->GetObject(self->peer_));
- if (thread_name != NULL) {
- SetThreadName(thread_name->ToModifiedUtf8().c_str());
- }
+ SirtRef<String> thread_name(self->GetName());
+ SetThreadName(thread_name->ToModifiedUtf8().c_str());
}
Dbg::PostThreadStart(self);
@@ -264,8 +262,6 @@
self->SetState(Thread::kNative);
- SetThreadName(name);
-
// If we're the main thread, ClassLinker won't be created until after we're attached,
// so that thread needs a two-stage attach. Regular threads don't need this hack.
if (self->thin_lock_id_ != ThreadList::kMainId) {
@@ -300,13 +296,22 @@
peer_ = DecodeJObject(peer.get());
SetVmData(peer_, Thread::Current());
- // Because we mostly run without code available (in the compiler, in tests), we
- // manually assign the fields the constructor should have set.
- // TODO: lose this.
- gThread_daemon->SetBoolean(peer_, thread_is_daemon);
- gThread_group->SetObject(peer_, Decode<Object*>(env, thread_group.get()));
- gThread_name->SetObject(peer_, Decode<Object*>(env, thread_name.get()));
- gThread_priority->SetInt(peer_, thread_priority);
+ SirtRef<String> peer_thread_name(GetName());
+ if (peer_thread_name.get() == NULL) {
+ // The Thread constructor should have set the Thread.name to a
+ // non-null value. However, because we can run without code
+ // available (in the compiler, in tests), we manually assign the
+ // fields the constructor should have set.
+ gThread_daemon->SetBoolean(peer_, thread_is_daemon);
+ gThread_group->SetObject(peer_, Decode<Object*>(env, thread_group.get()));
+ gThread_name->SetObject(peer_, Decode<Object*>(env, thread_name.get()));
+ gThread_priority->SetInt(peer_, thread_priority);
+ peer_thread_name.reset(GetName());
+ }
+ // thread_name may have been null, so don't trust this to be non-null
+ if (peer_thread_name.get() != NULL) {
+ SetThreadName(GetName()->ToModifiedUtf8().c_str());
+ }
// Pre-allocate an OutOfMemoryError for the double-OOME case.
ThrowNewException("Ljava/lang/OutOfMemoryError;",