From f21f11efd6883a80da7694d194d3f7653a9ccb99 Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Fri, 11 Apr 2014 19:38:11 -0600 Subject: [PATCH] fix broken Android build due to 617bd85 617bd85 broke the Android build by creating an unresolvable order-of-operations bug in classpath-android.cpp's MyClasspath::preBoot method. The problem is that, while JNIEnv::FindClass is supposed to initialize the class that it finds, this causes JniConstants::init to indirectly invoke native methods which are not registered until JNI_OnLoad is called (which happens after JniConstants::init is called). However, if we call JNI_OnLoad first, that causes methods to be invoked which rely on JniConstants::init having already been run. I haven't checked to see how Dalvik handles this, but I don't see any way around the problem besides disabling initialization by JNIEnv::FindClass until the preBoot phase is complete. Moreover, it's dangerous to allow Java code to be invoked so early anyway, since the VM is not yet fully initialized. --- src/avian/machine.h | 2 ++ src/classpath-android.cpp | 13 ++++++++++--- src/classpath-avian.cpp | 5 +++++ src/classpath-openjdk.cpp | 5 +++++ src/jnienv.cpp | 6 ++++-- 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/avian/machine.h b/src/avian/machine.h index 213e0bbe14..5197185b71 100644 --- a/src/avian/machine.h +++ b/src/avian/machine.h @@ -1571,6 +1571,8 @@ class Classpath { virtual void preBoot(Thread* t) = 0; + virtual bool mayInitClasses() = 0; + virtual void boot(Thread* t) = 0; diff --git a/src/classpath-android.cpp b/src/classpath-android.cpp index 5ec119b669..db7616f532 100644 --- a/src/classpath-android.cpp +++ b/src/classpath-android.cpp @@ -228,9 +228,8 @@ translateStackTrace(Thread* t, object raw) class MyClasspath : public Classpath { public: - MyClasspath(Allocator* allocator): - allocator(allocator), - tzdata(0) + MyClasspath(Allocator* allocator) + : allocator(allocator), tzdata(0), mayInitClasses_(false) { } virtual object @@ -493,6 +492,13 @@ class MyClasspath : public Classpath { JniConstants::init(reinterpret_cast<_JNIEnv*>(t)); JNI_OnLoad(reinterpret_cast< ::JavaVM*>(t->m), 0); + + mayInitClasses_ = true; + } + + virtual bool mayInitClasses() + { + return mayInitClasses_; } virtual void @@ -579,6 +585,7 @@ class MyClasspath : public Classpath { Allocator* allocator; System::Region* tzdata; + bool mayInitClasses_; }; int64_t JNICALL diff --git a/src/classpath-avian.cpp b/src/classpath-avian.cpp index 64c996a611..a0bb56501c 100644 --- a/src/classpath-avian.cpp +++ b/src/classpath-avian.cpp @@ -121,6 +121,11 @@ class MyClasspath : public Classpath { // ignore } + virtual bool mayInitClasses() + { + return true; + } + virtual void boot(Thread*) { diff --git a/src/classpath-openjdk.cpp b/src/classpath-openjdk.cpp index 723ce7e475..cb03ec8645 100644 --- a/src/classpath-openjdk.cpp +++ b/src/classpath-openjdk.cpp @@ -681,6 +681,11 @@ class MyClasspath : public Classpath { // ignore } + virtual bool mayInitClasses() + { + return true; + } + virtual void boot(Thread* t) { diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 725cbe354b..47531958be 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -354,9 +354,11 @@ findClass(Thread* t, uintptr_t* arguments) : root(t, Machine::AppLoader), n); - PROTECT(t, c); + if (t->m->classpath->mayInitClasses()) { + PROTECT(t, c); - initClass(t, c); + initClass(t, c); + } return reinterpret_cast(makeLocalReference(t, getJClass(t, c))); }