From 4d0207c3ed28bbbb8c583a3c3a37f00d1cd4dedc Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 3 Oct 2011 19:14:34 -0700 Subject: Wrap non-Error throwables in ExceptionInInitializerError. This doesn't fix test 084 because we still need the stub to ensure is run before static method invocation, but it gets us to the point where that's the only failure in the test, and that's already being worked on. Change-Id: I9835394a733421541d9687f66aeb3bef9f5dbb0e --- src/class_linker.cc | 39 ++++++++++++++++++++++++++++++++------- 1 file changed, 32 insertions(+), 7 deletions(-) (limited to 'src/class_linker.cc') diff --git a/src/class_linker.cc b/src/class_linker.cc index a8703dab91..b4e332d4f6 100644 --- a/src/class_linker.cc +++ b/src/class_linker.cc @@ -18,6 +18,7 @@ #include "monitor.h" #include "object.h" #include "runtime.h" +#include "ScopedLocalRef.h" #include "space.h" #include "thread.h" #include "UniquePtr.h" @@ -83,6 +84,35 @@ void ThrowEarlierClassFailure(Class* c) { } } +void WrapExceptionInInitializer() { + JNIEnv* env = Thread::Current()->GetJniEnv(); + + ScopedLocalRef cause(env, env->ExceptionOccurred()); + CHECK(cause.get() != NULL); + + env->ExceptionClear(); + + // TODO: add java.lang.Error to JniConstants? + ScopedLocalRef error_class(env, env->FindClass("java/lang/Error")); + CHECK(error_class.get() != NULL); + if (env->IsInstanceOf(cause.get(), error_class.get())) { + // We only wrap non-Error exceptions; an Error can just be used as-is. + env->Throw(cause.get()); + return; + } + + // TODO: add java.lang.ExceptionInInitializerError to JniConstants? + ScopedLocalRef eiie_class(env, env->FindClass("java/lang/ExceptionInInitializerError")); + CHECK(eiie_class.get() != NULL); + + jmethodID mid = env->GetMethodID(eiie_class.get(), "" , "(Ljava/lang/Throwable;)V"); + CHECK(mid != NULL); + + ScopedLocalRef eiie(env, + reinterpret_cast(env->NewObject(eiie_class.get(), mid, cause.get()))); + env->Throw(eiie.get()); +} + } const char* ClassLinker::class_roots_descriptors_[] = { @@ -1391,8 +1421,7 @@ bool ClassLinker::InitializeClass(Class* klass, bool can_run_clinit) { ObjectLock lock(klass); if (self->IsExceptionPending()) { - // TODO: if self->GetException() is not an Error, - // wrap in ExceptionInInitializerError + WrapExceptionInInitializer(); klass->SetStatus(Class::kStatusError); } else { ++Runtime::Current()->GetStats()->class_init_count; @@ -1415,11 +1444,7 @@ bool ClassLinker::WaitForInitializeClass(Class* klass, Thread* self, ObjectLock& // there's an exception pending (only possible if // "interruptShouldThrow" was set), bail out. if (self->IsExceptionPending()) { - // TODO: set cause of ExceptionInInitializerError to self->GetException() - self->ThrowNewExceptionF("Ljava/lang/ExceptionInInitializerError;", - "Exception %s thrown while initializing class %s", - PrettyTypeOf(self->GetException()).c_str(), - PrettyDescriptor(klass->GetDescriptor()).c_str()); + WrapExceptionInInitializer(); klass->SetStatus(Class::kStatusError); return false; } -- cgit v1.2.3-59-g8ed1b