summaryrefslogtreecommitdiff
path: root/runtime/class_linker.cc
diff options
context:
space:
mode:
author Andreas Gampe <agampe@google.com> 2015-11-02 16:20:00 -0800
committer Andreas Gampe <agampe@google.com> 2015-11-04 18:01:26 -0800
commitcb086955c2a21270cd2f53a8bce71e577d776506 (patch)
treebe580e6a4050539b2785d6d92cb9e71507c075d2 /runtime/class_linker.cc
parentaccc24985c08e98a27f43bc856fba4c3c48e79e9 (diff)
ART: Change behavior for rethrowing init failures (2)
Always store the pending exception when making a class erroneous. Instead of filtering by ExceptionInInitializerError, add an option to the rethrow that enforces a NoClassDefFoundError, which is required by the specification. Use the libcore companion change to add the stored error (if any) as a cause to the NoClassDefFoundError, which should significantly help tracking down issues. Fix run-test 008 to expect spec-compliant behavior. Test that a cause has been set. Bug: 25445103 Change-Id: I6a0dc54e78312283faf23415887eff387531407f
Diffstat (limited to 'runtime/class_linker.cc')
-rw-r--r--runtime/class_linker.cc15
1 files changed, 10 insertions, 5 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 6053469016..cdb7712211 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -153,7 +153,7 @@ static void HandleEarlierVerifyError(Thread* self, ClassLinker* class_linker, mi
self->AssertPendingException();
}
-void ClassLinker::ThrowEarlierClassFailure(mirror::Class* c) {
+void ClassLinker::ThrowEarlierClassFailure(mirror::Class* c, bool wrap_in_no_class_def) {
// The class failed to initialize on a previous attempt, so we want to throw
// a NoClassDefFoundError (v2 2.17.5). The exception to this rule is if we
// failed in verification, in which case v2 5.4.1 says we need to re-throw
@@ -178,10 +178,15 @@ void ClassLinker::ThrowEarlierClassFailure(mirror::Class* c) {
self->SetException(pre_allocated);
} else {
if (c->GetVerifyError() != nullptr) {
+ // Rethrow stored error.
HandleEarlierVerifyError(self, this, c);
- } else {
- self->ThrowNewException("Ljava/lang/NoClassDefFoundError;",
- PrettyDescriptor(c).c_str());
+ }
+ if (c->GetVerifyError() == nullptr || wrap_in_no_class_def) {
+ // If there isn't a recorded earlier error, or this is a repeat throw from initialization,
+ // the top-level exception must be a NoClassDefFoundError. The potentially already pending
+ // exception will be a cause.
+ self->ThrowNewWrappedException("Ljava/lang/NoClassDefFoundError;",
+ PrettyDescriptor(c).c_str());
}
}
}
@@ -3423,7 +3428,7 @@ bool ClassLinker::InitializeClass(Thread* self, Handle<mirror::Class> klass,
// Was the class already found to be erroneous? Done under the lock to match the JLS.
if (klass->IsErroneous()) {
- ThrowEarlierClassFailure(klass.Get());
+ ThrowEarlierClassFailure(klass.Get(), true);
VlogClassInitializationFailure(klass);
return false;
}