summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Brian Carlstrom <bdc@google.com> 2014-02-19 15:21:21 -0800
committer Brian Carlstrom <bdc@google.com> 2014-02-19 15:53:35 -0800
commit073278cd7129ff07dbcd6ccfabd2c34f47ec92ad (patch)
treec8dbc60d903653ecde81cef4d781128884859374
parenta3537fb03e092a82f08ceb670a2eafa703203465 (diff)
Do not FixupStaticTrampolines of uninitialized classes
Bug: 13027732 Change-Id: I5966d63afd8fbcd091801297290f117f3c9cb44c
-rw-r--r--runtime/class_linker.cc6
-rw-r--r--runtime/mirror/class-inl.h2
-rw-r--r--test/084-class-init/expected.txt2
-rw-r--r--test/084-class-init/src/Main.java30
4 files changed, 36 insertions, 4 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index f8a20d0617..fa50324c51 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -1684,6 +1684,7 @@ static bool NeedsInterpreter(mirror::ArtMethod* method, const void* quick_code,
}
void ClassLinker::FixupStaticTrampolines(mirror::Class* klass) {
+ DCHECK(klass->IsInitialized()) << PrettyDescriptor(klass);
if (klass->NumDirectMethods() == 0) {
return; // No direct methods => no static methods.
}
@@ -3159,9 +3160,6 @@ bool ClassLinker::InitializeClass(const SirtRef<mirror::Class>& klass, bool can_
}
}
- // Opportunistically set static method trampolines to their destination.
- FixupStaticTrampolines(klass.get());
-
uint64_t t1 = NanoTime();
bool success = true;
@@ -3185,6 +3183,8 @@ bool ClassLinker::InitializeClass(const SirtRef<mirror::Class>& klass, bool can_
ClassHelper kh(klass.get());
LOG(INFO) << "Initialized class " << kh.GetDescriptor() << " from " << kh.GetLocation();
}
+ // Opportunistically set static method trampolines to their destination.
+ FixupStaticTrampolines(klass.get());
}
}
return success;
diff --git a/runtime/mirror/class-inl.h b/runtime/mirror/class-inl.h
index 4c2bdb02dd..cba221d01f 100644
--- a/runtime/mirror/class-inl.h
+++ b/runtime/mirror/class-inl.h
@@ -41,7 +41,7 @@ inline uint32_t Class::GetObjectSize() {
inline Class* Class::GetSuperClass() {
// Can only get super class for loaded classes (hack for when runtime is
// initializing)
- DCHECK(IsLoaded() || !Runtime::Current()->IsStarted()) << IsLoaded();
+ DCHECK(IsLoaded() || IsErroneous() || !Runtime::Current()->IsStarted()) << IsLoaded();
return GetFieldObject<Class>(OFFSET_OF_OBJECT_MEMBER(Class, super_class_), false);
}
diff --git a/test/084-class-init/expected.txt b/test/084-class-init/expected.txt
index 13892147c2..d7a80bf741 100644
--- a/test/084-class-init/expected.txt
+++ b/test/084-class-init/expected.txt
@@ -8,3 +8,5 @@ SlowInit static block post-sleep
MethodThread message
Fields (child thread): 111222333444
Fields (main thread): 111222333444
+checkStaticMethodInvokeAfterFailedClinit START
+checkStaticMethodInvokeAfterFailedClinit PASSED
diff --git a/test/084-class-init/src/Main.java b/test/084-class-init/src/Main.java
index cf69570854..28eb3e923f 100644
--- a/test/084-class-init/src/Main.java
+++ b/test/084-class-init/src/Main.java
@@ -37,6 +37,7 @@ public class Main {
public static void main(String[] args) {
checkExceptions();
checkTiming();
+ checkStaticMethodInvokeAfterFailedClinit();
}
public static void sleep(int msec) {
@@ -128,4 +129,33 @@ public class Main {
SlowInit.printMsg("MethodThread message");
}
}
+
+ static void checkStaticMethodInvokeAfterFailedClinit() {
+ System.out.println("checkStaticMethodInvokeAfterFailedClinit START");
+
+ // Call static method to cause implicit clinit.
+ try {
+ ClassWithThrowingClinit.staticMethod();
+ System.out.println("checkStaticMethodInvokeAfterFailedClinit FAILED"
+ + " due to missing ExceptionInInitializerError");
+ } catch (ExceptionInInitializerError expected) {
+ }
+
+ // Call again to make sure we still get the expected error.
+ try {
+ ClassWithThrowingClinit.staticMethod();
+ System.out.println("checkStaticMethodInvokeAfterFailedClinit FAILED"
+ + " due to missing NoClassDefFoundError");
+ } catch (NoClassDefFoundError expected) {
+ }
+ System.out.println("checkStaticMethodInvokeAfterFailedClinit PASSED");
+ }
+
+ static class ClassWithThrowingClinit {
+ static {
+ throwDuringClinit();
+ }
+ static void staticMethod() {
+ }
+ }
}