/*
+ * Helper for dvmExceptionStartup(), which looks up classes and stores
+ * them to the indicated pointer, returning a failure code (false ==
+ * failure).
+ */
+static bool initRef(ClassObject** pClass, const char* name)
+{
+ ClassObject* result;
+
+ if (name[0] == '[') {
+ result = dvmFindArrayClass(name, NULL);
+ } else {
+ result = dvmFindSystemClassNoInit(name);
+ }
+
+ if (result == NULL) {
+ LOGE("Could not find exception class %s\n", name);
+ return false;
+ }
+
+ *pClass = result;
+ return true;
+}
+
+/*
* Cache pointers to some of the exception classes we use locally.
*
* Note this is NOT called during dexopt optimization. Some of the fields
*/
bool dvmExceptionStartup(void)
{
- gDvm.classJavaLangThrowable =
- dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
- gDvm.classJavaLangRuntimeException =
- dvmFindSystemClassNoInit("Ljava/lang/RuntimeException;");
- gDvm.classJavaLangStackOverflowError =
- dvmFindSystemClassNoInit("Ljava/lang/StackOverflowError;");
- gDvm.classJavaLangError =
- dvmFindSystemClassNoInit("Ljava/lang/Error;");
- gDvm.classJavaLangStackTraceElement =
- dvmFindSystemClassNoInit("Ljava/lang/StackTraceElement;");
- gDvm.classJavaLangStackTraceElementArray =
- dvmFindArrayClass("[Ljava/lang/StackTraceElement;", NULL);
- if (gDvm.classJavaLangThrowable == NULL ||
- gDvm.classJavaLangStackTraceElement == NULL ||
- gDvm.classJavaLangStackTraceElementArray == NULL)
- {
- LOGE("Could not find one or more essential exception classes\n");
+ bool ok = true;
+
+ ok &= initRef(&gDvm.exError, "Ljava/lang/Error;");
+ ok &= initRef(&gDvm.exExceptionInInitializerError,
+ "Ljava/lang/ExceptionInInitializerError;");
+ ok &= initRef(&gDvm.exRuntimeException, "Ljava/lang/RuntimeException;");
+ ok &= initRef(&gDvm.exStackOverflowError,
+ "Ljava/lang/StackOverflowError;");
+ ok &= initRef(&gDvm.exThrowable, "Ljava/lang/Throwable;");
+ ok &= initRef(&gDvm.classJavaLangStackTraceElement,
+ "Ljava/lang/StackTraceElement;");
+ ok &= initRef(&gDvm.classJavaLangStackTraceElementArray,
+ "[Ljava/lang/StackTraceElement;");
+
+ if (!ok) {
return false;
}
/* grab an offset for the stackData field */
gDvm.offJavaLangThrowable_stackState =
- dvmFindFieldOffset(gDvm.classJavaLangThrowable,
+ dvmFindFieldOffset(gDvm.exThrowable,
"stackState", "Ljava/lang/Object;");
if (gDvm.offJavaLangThrowable_stackState < 0) {
LOGE("Unable to find Throwable.stackState\n");
/* and one for the cause field, just 'cause */
gDvm.offJavaLangThrowable_cause =
- dvmFindFieldOffset(gDvm.classJavaLangThrowable,
+ dvmFindFieldOffset(gDvm.exThrowable,
"cause", "Ljava/lang/Throwable;");
if (gDvm.offJavaLangThrowable_cause < 0) {
LOGE("Unable to find Throwable.cause\n");
return false;
}
+ /*
+ * ExceptionInInitializerError is used in the guts of Class.c; it
+ * wants to call the constructor more directly, so look that up
+ * explicitly, here.
+ */
+ gDvm.methJavaLangExceptionInInitializerError_init =
+ dvmFindDirectMethodByDescriptor(gDvm.exExceptionInInitializerError,
+ "<init>", "(Ljava/lang/Throwable;)V");
+ if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
+ LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
+ return false;
+ }
+
return true;
}
}
if (cause != NULL) {
- if (!dvmInstanceof(cause->clazz, gDvm.classJavaLangThrowable)) {
+ if (!dvmInstanceof(cause->clazz, gDvm.exThrowable)) {
LOGE("Tried to init exception with cause '%s'\n",
cause->clazz->descriptor);
dvmAbort();
excepClass->descriptor, msg, initKind);
assert(strcmp(excepClass->descriptor,
"Ljava/lang/RuntimeException;") != 0);
- dvmThrowChainedException("Ljava/lang/RuntimeException;",
+ dvmThrowChainedExceptionByClass(gDvm.exRuntimeException,
"re-throw on exception class missing constructor", NULL);
goto bail;
}
*/
bool dvmIsCheckedException(const Object* exception)
{
- if (dvmInstanceof(exception->clazz, gDvm.classJavaLangError) ||
- dvmInstanceof(exception->clazz, gDvm.classJavaLangRuntimeException))
+ if (dvmInstanceof(exception->clazz, gDvm.exError) ||
+ dvmInstanceof(exception->clazz, gDvm.exRuntimeException))
{
return false;
} else {
*/
Object* dvmGetExceptionCause(const Object* exception)
{
- if (!dvmInstanceof(exception->clazz, gDvm.classJavaLangThrowable)) {
+ if (!dvmInstanceof(exception->clazz, gDvm.exThrowable)) {
LOGE("Tried to get cause from object of type '%s'\n",
exception->clazz->descriptor);
dvmAbort();
if (dvmIsBreakFrame((u4*)fp))
break;
- if (!dvmInstanceof(method->clazz, gDvm.classJavaLangThrowable))
+ if (!dvmInstanceof(method->clazz, gDvm.exThrowable))
break;
//LOGD("EXCEP: ignoring %s.%s\n",
// method->clazz->descriptor, method->name);
}
void dvmThrowRuntimeException(const char* msg) {
- dvmThrowException("Ljava/lang/RuntimeException;", msg);
+ dvmThrowExceptionByClass(gDvm.exRuntimeException, msg);
}
void dvmThrowStaleDexCacheError(const char* msg) {
*/
ClassObject* classJavaLangClass;
ClassObject* classJavaLangClassArray;
- ClassObject* classJavaLangError;
ClassObject* classJavaLangObject;
ClassObject* classJavaLangObjectArray;
- ClassObject* classJavaLangRuntimeException;
ClassObject* classJavaLangString;
ClassObject* classJavaLangThread;
ClassObject* classJavaLangVMThread;
ClassObject* classJavaLangThreadGroup;
- ClassObject* classJavaLangThrowable;
- ClassObject* classJavaLangStackOverflowError;
ClassObject* classJavaLangStackTraceElement;
ClassObject* classJavaLangStackTraceElementArray;
ClassObject* classJavaLangAnnotationAnnotationArray;
ClassObject* classJavaLangReflectMethod;
ClassObject* classJavaLangReflectMethodArray;
ClassObject* classJavaLangReflectProxy;
- ClassObject* classJavaLangExceptionInInitializerError;
ClassObject* classJavaLangRefPhantomReference;
ClassObject* classJavaLangRefReference;
ClassObject* classJavaNioReadWriteDirectByteBuffer;
ClassObject* classOrgApacheHarmonyLangAnnotationAnnotationMember;
ClassObject* classOrgApacheHarmonyLangAnnotationAnnotationMemberArray;
+ /*
+ * classes representing exception types. The names here don't include
+ * packages, just to keep the use sites a bit less verbose. All are
+ * in java.lang, except where noted.
+ */
+ ClassObject* exError;
+ ClassObject* exExceptionInInitializerError;
+ ClassObject* exRuntimeException;
+ ClassObject* exStackOverflowError;
+ ClassObject* exThrowable;
+
/* synthetic classes for arrays of primitives */
ClassObject* classArrayBoolean;
ClassObject* classArrayChar;
foundPossibleHandler = true;
if (handler->typeIdx == kDexNoIndex)
- clazz = gDvm.classJavaLangThrowable;
+ clazz = gDvm.exThrowable;
else
clazz = dvmOptResolveClass(meth->clazz, handler->typeIdx,
&localFailure);
if (gDvm.classJavaLangString == NULL)
gDvm.classJavaLangString =
dvmFindSystemClassNoInit("Ljava/lang/String;");
- if (gDvm.classJavaLangThrowable == NULL) {
- gDvm.classJavaLangThrowable =
+ if (gDvm.exThrowable == NULL) {
+ gDvm.exThrowable =
dvmFindSystemClassNoInit("Ljava/lang/Throwable;");
gDvm.offJavaLangThrowable_cause =
- dvmFindFieldOffset(gDvm.classJavaLangThrowable,
+ dvmFindFieldOffset(gDvm.exThrowable,
"cause", "Ljava/lang/Throwable;");
}
if (gDvm.classJavaLangObject == NULL)
case OP_THROW:
resClass = getClassFromRegister(workLine, decInsn.vA, &failure);
if (VERIFY_OK(failure) && resClass != NULL) {
- if (!dvmInstanceof(resClass, gDvm.classJavaLangThrowable)) {
+ if (!dvmInstanceof(resClass, gDvm.exThrowable)) {
LOG_VFY("VFY: thrown class %s not instanceof Throwable\n",
resClass->descriptor);
failure = VERIFY_ERROR_GENERIC;
*/
static void throwClinitError(void)
{
+ if (gDvm.exExceptionInInitializerError == NULL) {
+ /*
+ * ExceptionInInitializerError isn't itself initialized. This
+ * can happen very early during VM startup if there is a
+ * problem with one of the corest-of-the-core classes, and it
+ * can possibly happen during a dexopt run. Rather than do
+ * anything fancier, we just abort here with a blatant
+ * message.
+ */
+ LOGE("Fatal error during early class initialization:\n");
+ dvmLogExceptionStackTrace();
+ dvmAbort();
+ }
+
Thread* self = dvmThreadSelf();
- Object* exception;
- Object* eiie;
+ Object* exception = dvmGetException(self);
- exception = dvmGetException(self);
dvmAddTrackedAlloc(exception, self);
dvmClearException(self);
- if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
- /*
- * Always resolves to same thing -- no race condition.
- */
- gDvm.classJavaLangExceptionInInitializerError =
- dvmFindSystemClass(
- "Ljava/lang/ExceptionInInitializerError;");
- if (gDvm.classJavaLangExceptionInInitializerError == NULL) {
- LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
- goto fail;
- }
-
- gDvm.methJavaLangExceptionInInitializerError_init =
- dvmFindDirectMethodByDescriptor(gDvm.classJavaLangExceptionInInitializerError,
- "<init>", "(Ljava/lang/Throwable;)V");
- if (gDvm.methJavaLangExceptionInInitializerError_init == NULL) {
- LOGE("Unable to prep java/lang/ExceptionInInitializerError\n");
- goto fail;
- }
- }
-
- eiie = dvmAllocObject(gDvm.classJavaLangExceptionInInitializerError,
- ALLOC_DEFAULT);
+ Object* eiie =
+ dvmAllocObject(gDvm.exExceptionInInitializerError, ALLOC_DEFAULT);
if (eiie == NULL)
goto fail;