Пример #1
0
static void wrapClassNotFoundException(Env* env, const char* className) {
    Object* exception = rvmExceptionOccurred(env);
    if (exception && exception->clazz == java_lang_ClassNotFoundException) {
        // If ClassNotFoundException is thrown we have to wrap it in a NoClassDefFoundError
        exception = rvmExceptionClear(env);
        Method* constructor = rvmGetInstanceMethod(env, java_lang_NoClassDefFoundError, "<init>", "(Ljava/lang/String;)V");
        if (!constructor) return;
        Object* message = rvmNewStringUTF(env, className, -1);
        if (!message) return;
        Object* wrappedException = rvmNewObject(env, java_lang_NoClassDefFoundError, constructor, message);
        if (!wrappedException) return;
        Class* java_lang_StackTraceElement = rvmFindClassUsingLoader(env, "java/lang/StackTraceElement", NULL);
        if (!java_lang_StackTraceElement) return;
        ObjectArray* stackTrace = rvmNewObjectArray(env, 0, java_lang_StackTraceElement, NULL, NULL);
        if (!stackTrace) return;
        Method* setStackTrace = rvmGetInstanceMethod(env, java_lang_Throwable, "setStackTrace", "([Ljava/lang/StackTraceElement;)V");
        if (!setStackTrace) return;
        rvmCallVoidInstanceMethod(env, wrappedException, setStackTrace, stackTrace);
        if (rvmExceptionCheck(env)) return;
        Method* initCause = rvmGetInstanceMethod(env, java_lang_NoClassDefFoundError, "initCause", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
        if (!initCause) return;
        rvmCallObjectInstanceMethod(env, wrappedException, initCause, exception);
        if (!rvmExceptionCheck(env)) rvmThrow(env, wrappedException);
    }
}
Пример #2
0
void* lookupInterfaceMethod(Env* env, ClassInfoHeader* header, Object* thiz, char* name, char* desc) {
    initializeClass(env, header);
    if (rvmExceptionCheck(env)) return NULL;
    Class* ownerInterface = header->clazz;
    if (!rvmIsInstanceOf(env, thiz, ownerInterface)) {
        char message[256];
        snprintf(message, 256, "Class %s does not implement the requested interface %s", 
            rvmToBinaryClassName(env, thiz->clazz->name), rvmToBinaryClassName(env, ownerInterface->name));
        rvmThrowIncompatibleClassChangeError(env, message);
        return NULL;
    }
    Method* method = rvmGetInstanceMethod(env, thiz->clazz, name, desc);
    Object* throwable = rvmExceptionClear(env);
    if (!method && throwable->clazz != java_lang_NoSuchMethodError) { 
        rvmThrow(env, throwable);
        return NULL;
    }
    if (!method || METHOD_IS_ABSTRACT(method)) {
        rvmThrowAbstractMethodError(env, ""); // TODO: Message
        return NULL;
    }
    if (!METHOD_IS_PUBLIC(method)) {
        rvmThrowIllegalAccessError(env, ""); // TODO: Message
        return NULL;
    }
    return method->synchronizedImpl ? method->synchronizedImpl : method->impl;
}
Пример #3
0
void rvmRaiseException(Env* env, Object* e) {
    if (env->throwable != e) {
        rvmThrow(env, e);
    }
    jboolean (*exceptionMatch)(Env*, TrycatchContext*) = env->vm->options->exceptionMatch;
    TrycatchContext* tc = env->trycatchContext;
    while (tc) {
        if (tc->sel != 0 && (tc->sel == CATCH_ALL_SEL || exceptionMatch(env, tc))) {
            rvmRestoreThreadSignalMask(env);
            rvmHookExceptionRaised(env, e, tc->prev? TRUE: FALSE);
            rvmTrycatchJump(tc);
            // unreachable
        }
        rvmTrycatchLeave(env);
        tc = env->trycatchContext;
    }

    /*
     * We only end up here if Java was called into from native without a
     * TrycatchContext being set up first. This only happens for @Callback
     * methods. The only sane thing to do here is to terminate the app. But
     * first we want to detach the current thread which will report the
     * uncaught exception to the uncaught exception handler.
     */
    env->gatewayFrames = NULL; // Needed to avoid the "Cannot detach thread when there are non native frames on the call stack" error
    rvmDetachCurrentThread(env->vm, TRUE, TRUE);
    rvmAbort("Unhandled exception (probably in a @Callback method called from native code): %s", e->clazz->name);
}
Пример #4
0
jboolean rvmThrowOutOfMemoryError(Env* env) {
    // Don't run the constructor on OutOfMemoryError instances since that will
    // likely cause more OOM.
    Object* e = rvmAllocateObject(env, java_lang_OutOfMemoryError);
    if (!e) {
        return FALSE;
    }
    rvmThrow(env, e);
    return TRUE;
}
Пример #5
0
jboolean rvmThrowNew(Env* env, Class* clazz, const char* message) {
    Method* constructor = rvmGetInstanceMethod(env, clazz, "<init>", "(Ljava/lang/String;)V");
    if (!constructor) return FALSE;
    Object* string = NULL;
    // TODO: Check that clazz != NULL?
    if (message) {
        string = rvmNewStringUTF(env, message, -1);
        if (!string) return FALSE;
    }
    Object* e = rvmNewObject(env, clazz, constructor, string);
    if (!e) return FALSE;
    rvmThrow(env, e);
    return TRUE;
}
Пример #6
0
void throwInvocationTargetException(Env* env, Object* throwable) {
    rvmExceptionClear(env);
    if (!java_lang_reflect_InvocationTargetException) {
        java_lang_reflect_InvocationTargetException = rvmFindClassUsingLoader(env, "java/lang/reflect/InvocationTargetException", NULL);
        if (!java_lang_reflect_InvocationTargetException) return;
    }
    if (!java_lang_reflect_InvocationTargetException_init) {
        java_lang_reflect_InvocationTargetException_init = rvmGetMethod(env, java_lang_reflect_InvocationTargetException, "<init>", "(Ljava/lang/Throwable;)V");
        if (!java_lang_reflect_InvocationTargetException_init) return;
    }
    jvalue initArgs[1];
    initArgs[0].l = (jobject) throwable;
    Object* exception = rvmNewObjectA(env, java_lang_reflect_InvocationTargetException, java_lang_reflect_InvocationTargetException_init, initArgs);
    if (!exception) return;
    rvmThrow(env, exception);
}
Пример #7
0
void rvmRaiseException(Env* env, Object* e) {
    if (env->throwable != e) {
        rvmThrow(env, e);
    }
    jboolean (*exceptionMatch)(Env*, TrycatchContext*) = env->vm->options->exceptionMatch;
    TrycatchContext* tc = env->trycatchContext;
    while (tc) {
        if (tc->sel != 0 && (tc->sel == CATCH_ALL_SEL || exceptionMatch(env, tc))) {
            rvmRestoreSignalMask(env);
            rvmTrycatchJump(tc);
            // unreachable
        }
        rvmTrycatchLeave(env);
        tc = env->trycatchContext;
    }
    rvmAbort("Unhandled exception: %s", e->clazz->name);
}
Пример #8
0
static jint Throw(JNIEnv* env, jthrowable obj) {
    rvmThrow((Env*) env, (Object*) obj);
    return 0;
}
Пример #9
0
void rvmInitialize(Env* env, Class* clazz) {
    obtainClassLock();
    // TODO: Throw java.lang.NoClassDefFoundError if state == CLASS_ERROR?
    if (CLASS_IS_STATE_ERROR(clazz)) {
        // TODO: Add the class' binary name in the message
        rvmThrowNew(env, java_lang_NoClassDefFoundError, "Could not initialize class ??");
        releaseClassLock();
        return;
    }
    if (!CLASS_IS_STATE_INITIALIZED(clazz) && !CLASS_IS_STATE_INITIALIZING(clazz)) {
        jint oldState = clazz->flags & CLASS_STATE_MASK;
        clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_INITIALIZING;
        if (clazz->superclass) {
            rvmInitialize(env, clazz->superclass);
            if (rvmExceptionOccurred(env)) {
                clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | oldState;
                releaseClassLock();
                return;
            }
        }

        TRACEF("Initializing class %s", clazz->name);
        void* initializer = clazz->initializer;
        if (!initializer) {
            if (!CLASS_IS_ARRAY(clazz) && !CLASS_IS_PROXY(clazz) && !CLASS_IS_PRIMITIVE(clazz)) {
                env->vm->options->classInitialized(env, clazz);
            }
            clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_INITIALIZED;
            releaseClassLock();
            return;
        }

        CallInfo* callInfo = call0AllocateCallInfo(env, initializer, 1, 0, 0, 0, 0);
        call0AddPtr(callInfo, env);
        void (*f)(CallInfo*) = (void (*)(CallInfo*)) _call0;
        rvmPushGatewayFrame(env);
        TrycatchContext tc = {0};
        tc.sel = CATCH_ALL_SEL;
        if (!rvmTrycatchEnter(env, &tc)) {
            f(callInfo);
        }
        rvmTrycatchLeave(env);
        rvmPopGatewayFrame(env);

        Object* exception = rvmExceptionClear(env);
        if (exception) {
            clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_ERROR;
            if (!rvmIsInstanceOf(env, exception, java_lang_Error)) {
                // If exception isn't an instance of java.lang.Error 
                // we must wrap it in a java.lang.ExceptionInInitializerError
                Method* constructor = rvmGetInstanceMethod(env, java_lang_ExceptionInInitializerError, "<init>", "(Ljava/lang/Throwable;)V");
                if (!constructor) return;
                Object* wrappedException = rvmNewObject(env, java_lang_ExceptionInInitializerError, constructor, exception);
                if (!wrappedException) return;
                exception = wrappedException;
            }
            rvmThrow(env, exception);
            releaseClassLock();
            return;
        }
        if (!CLASS_IS_ARRAY(clazz) && !CLASS_IS_PROXY(clazz) && !CLASS_IS_PRIMITIVE(clazz)) {
            env->vm->options->classInitialized(env, clazz);
        }
        clazz->flags = (clazz->flags & (~CLASS_STATE_MASK)) | CLASS_STATE_INITIALIZED;
    }
    releaseClassLock();
}