Ejemplo n.º 1
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);
}
Ejemplo n.º 2
0
Archivo: bc.c Proyecto: crjohns/robovm
Env* _bcAttachThreadFromCallback(void) {
    Env* env = NULL;
    if (rvmAttachCurrentThread(vm, &env, NULL, NULL) != JNI_OK) {
        rvmAbort("Failed to attach thread in callback");
    }
    return env;
}
Ejemplo n.º 3
0
void __android_log_assert(const char *cond, const char *tag,
			  const char *fmt, ...) {
    char realtag[128] = "android.";
    strcat(realtag, tag);
    va_list ap;
    va_start(ap, fmt);
    rvmLogfv(LOG_LEVEL_FATAL, realtag, fmt, ap);
    va_end(ap);
    rvmAbort(NULL);
}
Ejemplo n.º 4
0
Archivo: bc.c Proyecto: SinoJerk/robovm
Env* _bcAttachThreadFromCallback(void) {
    Env* env = rvmGetEnv();
    if (!env) {
        // This thread has never been attached or it has been
        // attached, then detached in the TLS destructor. In the
        // latter case, we are getting called back by native code
        // e.g. an auto-release pool, that is triggered after
        // the TLS destructor.
        if (rvmAttachCurrentThreadAsDaemon(vm, &env, NULL, NULL) != JNI_OK) {
            rvmAbort("Failed to attach thread in callback");
        }
    }
    return env;
}
Ejemplo n.º 5
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);
}
Ejemplo n.º 6
0
static jint detachThread(Env* env, jboolean ignoreAttachCount) {
    env->attachCount--;
    if (!ignoreAttachCount && env->attachCount > 0) {
        return JNI_OK;
    }

    if (env->gatewayFrames) {
        rvmAbort("Cannot detach thread when there are non native frames on the call stack");
    }

    // TODO: Release all monitors still held by this thread (should only be monitors acquired from JNI code)

    Thread* thread = env->currentThread;

    if (rvmExceptionOccurred(env)) {
        threadExitUncaughtException(env, thread);
    }

    if (thread->threadObj->group) {
        rvmCallVoidInstanceMethod(env, thread->threadObj->group, removeThreadMethod, thread->threadObj);
        rvmExceptionClear(env);
    }

    // Set threadPtr to null
    rvmAtomicStoreLong(&thread->threadObj->threadPtr, 0);

    // Notify anyone waiting on this thread (using Thread.join())
    rvmLockObject(env, thread->threadObj->lock);
    rvmObjectNotifyAll(env, thread->threadObj->lock);
    rvmUnlockObject(env, thread->threadObj->lock);

    rvmLockThreadsList();
    thread->status = THREAD_ZOMBIE;
    DL_DELETE(threads, thread);
    pthread_cond_broadcast(&threadsChangedCond);
    rvmTearDownSignals(env);
    env->currentThread = NULL;
    pthread_setspecific(tlsEnvKey, NULL);
    rvmUnlockThreadsList();

    return JNI_OK;
}
Ejemplo n.º 7
0
void rvmThrow(Env* env, Object* e) {
    // TODO: Check that e != NULL?
    if (env->throwable) {
        rvmAbort("rvmThrow() called with env->throwable already set");
    }
    if (IS_TRACE_ENABLED) {
        jlong stackState = rvmGetLongInstanceFieldValue(env, e, stackStateField);
        CallStack* callStack = (CallStack*) LONG_TO_PTR(stackState);
        if (!callStack || callStack->length == 0) {
            TRACEF("Throwing a %s with empty call stack", e->clazz->name);
        } else {
            TRACEF("Throwing a %s. Call stack:", e->clazz->name);
            Method* m;
            jint index = 0;
            while ((m = rvmGetNextCallStackMethod(env, callStack, &index)) != NULL) {
                TRACEF("    %s.%s%s", m->clazz->name, m->name, m->desc);
            }
        }
    }
    env->throwable = e;
}
Ejemplo n.º 8
0
static Class* findClass(Env* env, const char* className, ClassLoader* classLoader, Class* (*loaderFunc)(Env*, const char*, ClassLoader*)) {
    obtainClassLock();
    Class* clazz = getLoadedClass(env, className);
    if (clazz != NULL) {
        releaseClassLock();
        return clazz;
    }

    if (className[0] == '[') {
        Class* componentType = findClassByDescriptor(env, &className[1], classLoader, loaderFunc);
        if (!componentType)  {
            releaseClassLock();
            return NULL;
        }
        clazz = createArrayClass(env, componentType);
        releaseClassLock();
        return clazz;
    }

    TRACEF("Class '%s' not loaded", className);

    clazz = loaderFunc(env, className, classLoader);
    if (rvmExceptionOccurred(env)) {
        releaseClassLock();
        return NULL;
    }

    if (clazz == NULL) {
        if (!strcmp(className, "java/lang/ClassNotFoundException")) {
            rvmAbort("Fatal error: java.lang.ClassNotFoundException not found!");
        }
        rvmThrowClassNotFoundException(env, className);
    }

    TRACEF("Class '%s' loaded successfully", className);
    releaseClassLock();
    return clazz;
}
Ejemplo n.º 9
0
jboolean rvmInitOptions(int argc, char* argv[], Options* options, jboolean ignoreRvmArgs) {
    if (argc > 0) {
        // We're called from a RoboVM executable
        if (!realpath(argv[0], options->imagePath)) {
            return FALSE;
        }
    } else {
        // We're called via JNI. The caller could already have set
        // imagePath. If not we try to determine it via dladdr().
        if (strlen(options->imagePath) == 0) {
            Dl_info dlinfo;
            if (dladdr(rvmInitOptions, &dlinfo) == 0 || dlinfo.dli_fname == NULL) {
                rvmAbort("Could not determine image path using dladdr()");
            }
            strncpy(options->imagePath, dlinfo.dli_fname, sizeof(options->imagePath) - 1);
        }
    }

    if (strlen(options->resourcesPath) == 0) {
        strncpy(options->resourcesPath, options->imagePath, sizeof(options->resourcesPath) - 1);
        jint i = strlen(options->resourcesPath);
        while (i >= 0 && options->resourcesPath[i] != '/') {
            options->resourcesPath[i--] = '\0';
        }
        if (i >= 0 && options->resourcesPath[i] == '/') {
            options->resourcesPath[i] = '\0';
        }
        if (argc == 0) {
#if defined(DARWIN)
            // Called via JNI and on Darwin. Assume this is a framework. Use the
            // Resources folder next to the image.
            strncat(options->resourcesPath, "/Resources",
                    sizeof(options->resourcesPath) - strlen(options->resourcesPath) - 1);
#endif
        }
    }

    // Look for a robovm.ini in the resources path
    parseRoboVMIni(options);

    if (argc > 0) {
        jint firstJavaArg = 1;
        for (jint i = 1; i < argc; i++) {
            if (startsWith(argv[i], "-rvm:")) {
                if (!ignoreRvmArgs) {
                    char* arg = &argv[i][5];
                    rvmParseOption(arg, options);
                }
                firstJavaArg++;
            } else {
                break;
            }
        }

        options->commandLineArgs = NULL;
        options->commandLineArgsCount = argc - firstJavaArg;
        if (options->commandLineArgsCount > 0) {
            options->commandLineArgs = &argv[firstJavaArg];
        }

        return options->mainClass != NULL;
    }

    return TRUE;
}
Ejemplo n.º 10
0
static void FatalError(JNIEnv* env, const char* msg) {
    rvmAbort((char*) msg);
}