Object* rvmNewObjectV(Env* env, Class* clazz, Method* method, va_list args) { Object* obj = rvmAllocateObject(env, clazz); if (!obj) return NULL; rvmCallNonvirtualVoidInstanceMethodV(env, obj, method, args); if (rvmExceptionOccurred(env)) return NULL; return obj; }
Object* Java_aura_rt_VM_allocateObject(Env* env, Class* c, Class* cls) { Object *o = rvmAllocateObject(env, cls); if (o && CLASS_IS_FINALIZABLE(cls)) { rvmRegisterFinalizer(env, o); } return o; }
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; }
static void signalHandler_npe_so(int signum, siginfo_t* info, void* context) { // rvmGetEnv() uses pthread_getspecific() which isn't listed as // async-signal-safe. Others (e.g. mono) do this too so we assume it is safe // in practice. Env* env = rvmGetEnv(); if (env && rvmIsNonNativeFrame(env)) { // We now know the fault occurred in non-native code and not in our // native code or in any non-async-signal-safe system function. It // should be safe to do things here that would normally be unsafe to do // in a signal handler. void* faultAddr = info->si_addr; void* stackAddr = env->currentThread->stackAddr; Class* exClass = NULL; if (faultAddr < stackAddr && faultAddr >= (void*) (stackAddr - THREAD_STACK_GUARD_SIZE)) { // StackOverflowError exClass = java_lang_StackOverflowError; } else { // At least on Linux x86 it seems like si_addr isn't always 0x0 even // if a read of address 0x0 triggered SIGSEGV so we assume // everything that isn't a stack overflow is a read of address 0x0 // and throw NullPointerException. exClass = java_lang_NullPointerException; } if (exClass) { Object* throwable = rvmAllocateObject(env, exClass); if (!throwable) { throwable = rvmExceptionClear(env); } Frame fakeFrame; fakeFrame.prev = (Frame*) getFramePointer((ucontext_t*) context); fakeFrame.returnAddress = getPC((ucontext_t*) context); CallStack* callStack = captureCallStackFromFrame(env, &fakeFrame); rvmSetLongInstanceFieldValue(env, throwable, stackStateField, PTR_TO_LONG(callStack)); rvmRaiseException(env, throwable); } } struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = SIG_DFL; sigaction(signum, &sa, NULL); kill(0, signum); }
static void signalHandler_npe_so(int signum, siginfo_t* info, void* context) { // SIGSEGV/SIGBUS are synchronous signals so we shouldn't have to worry about only calling // async-signal-safe functions here. Env* env = rvmGetEnv(); if (env && rvmIsNonNativeFrame(env)) { // We now know the fault occurred in non-native code. void* faultAddr = info->si_addr; void* stackAddr = env->currentThread->stackAddr; Class* exClass = NULL; if (faultAddr < stackAddr && faultAddr >= (void*) (stackAddr - THREAD_STACK_GUARD_SIZE)) { // StackOverflowError exClass = java_lang_StackOverflowError; } else { // At least on Linux x86 it seems like si_addr isn't always 0x0 even // if a read of address 0x0 triggered SIGSEGV so we assume // everything that isn't a stack overflow is a read of address 0x0 // and throw NullPointerException. exClass = java_lang_NullPointerException; } if (exClass) { Frame fakeFrame; fakeFrame.prev = (Frame*) getFramePointer((ucontext_t*) context); fakeFrame.returnAddress = getPC((ucontext_t*) context); Object* throwable = NULL; CallStack* callStack = captureCallStackFromFrame(env, &fakeFrame); if (callStack) { throwable = rvmAllocateObject(env, exClass); if (throwable) { rvmCallVoidClassMethod(env, exClass, throwableInitMethod, throwable, PTR_TO_LONG(callStack)); if (rvmExceptionCheck(env)) { throwable = NULL; } } } if (!throwable) { throwable = rvmExceptionClear(env); } rvmRaiseException(env, throwable); // Never returns! } } }
Object* _bcAllocate(Env* env, ClassInfoHeader* header) { ENTER; Object* obj = rvmAllocateObject(env, header->clazz); LEAVE(obj); }
static jobject AllocObject(JNIEnv* env, jclass clazz) { return (jobject) rvmAllocateObject((Env*) env, (Class*) clazz); }
static jint attachThread(VM* vm, Env** envPtr, char* name, Object* group, jboolean daemon) { Env* env = *envPtr; // env is NULL if rvmAttachCurrentThread() was called. If non NULL rvmInitThreads() was called. if (!env) { // If the thread was already attached there's an Env* associated with the thread. env = (Env*) pthread_getspecific(tlsEnvKey); if (env) { env->attachCount++; *envPtr = env; return JNI_OK; } } if (!env) { env = rvmCreateEnv(vm); if (!env) goto error; } setThreadEnv(env); if (rvmExceptionOccurred(env)) goto error; Thread* thread = allocThread(env); if (!thread) goto error; thread->stackAddr = getStackAddress(); thread->pThread = pthread_self(); env->currentThread = thread; rvmChangeThreadStatus(env, thread, THREAD_RUNNING); JavaThread* threadObj = (JavaThread*) rvmAllocateObject(env, java_lang_Thread); if (!threadObj) goto error; rvmLockThreadsList(); if (!initThread(env, thread, threadObj)) { rvmUnlockThreadsList(); goto error; } if (!rvmSetupSignals(env)) { rvmUnlockThreadsList(); goto error; } DL_PREPEND(threads, thread); pthread_cond_broadcast(&threadsChangedCond); rvmUnlockThreadsList(); Object* threadName = NULL; if (name) { threadName = rvmNewStringUTF(env, name, -1); if (!threadName) goto error_remove; } Method* threadConstructor = rvmGetInstanceMethod2(env, java_lang_Thread, "<init>", "(JLjava/lang/String;Ljava/lang/ThreadGroup;Z)V"); if (!threadConstructor) goto error_remove; rvmCallNonvirtualVoidInstanceMethod(env, (Object*) threadObj, threadConstructor, PTR_TO_LONG(thread), threadName, group, daemon); if (rvmExceptionOccurred(env)) goto error_remove; *envPtr = env; return JNI_OK; error_remove: rvmLockThreadsList(); DL_DELETE(threads, thread); pthread_cond_broadcast(&threadsChangedCond); rvmTearDownSignals(env); rvmUnlockThreadsList(); error: if (env) env->currentThread = NULL; clearThreadEnv(); return JNI_ERR; }
Object* Java_sun_misc_Unsafe_allocateInstance(Env* env, Object* unsafe, Class* c) { return rvmAllocateObject(env, c); }