jdouble rvmCallDoubleClassMethodA(Env* env, Class* clazz, Method* method, jvalue* args) { CallInfo* callInfo = INIT_CALL_INFO(env, NULL, method, FALSE, args); if (!callInfo) return 0.0; rvmInitialize(env, method->clazz); if (rvmExceptionOccurred(env)) return 0.0; return callDoubleMethod(env, callInfo); }
Class* Java_java_lang_Class_classForName(Env* env, Class* cls, Object* className, jboolean initializeBoolean, ClassLoader* classLoader) { if (!className) { rvmThrowNullPointerException(env); return NULL; } char* classNameUTF = toBinaryName(env, className); if (!classNameUTF) return NULL; Class* clazz = rvmFindClassUsingLoader(env, classNameUTF, classLoader); if (!clazz) { char* p = classNameUTF; while (*p != '\0') { if (*p == '/') *p = '.'; p++; } WARNF("Class.forName() failed to load '%s'. " "Use the -forcelinkclasses command line option " "or add <forceLinkClasses><pattern>%s</pattern></forceLinkClasses> " "to your robovm.xml file to link it in.", classNameUTF, classNameUTF); return NULL; } if (initializeBoolean) { rvmInitialize(env, clazz); if (rvmExceptionCheck(env)) return NULL; } return clazz; }
Object* rvmAllocateObject(Env* env, Class* clazz) { if (CLASS_IS_ABSTRACT(clazz) || CLASS_IS_INTERFACE(clazz)) { // TODO: Message rvmThrowNew(env, java_lang_InstantiationException, ""); return NULL; } rvmInitialize(env, clazz); if (rvmExceptionOccurred(env)) return NULL; Object* obj = rvmAllocateMemoryForObject(env, clazz); if (!obj) return NULL; obj->clazz = clazz; return obj; }
jboolean rvmInitMemory(Env* env) { vm = env->vm; java_lang_ref_Reference = rvmFindClassUsingLoader(env, "java/lang/ref/Reference", NULL); if (!java_lang_ref_Reference) return FALSE; java_lang_ref_Reference_referent = rvmGetInstanceField(env, java_lang_ref_Reference, "referent", "Ljava/lang/Object;"); if (!java_lang_ref_Reference_referent) return FALSE; java_lang_ref_Reference_pendingNext = rvmGetInstanceField(env, java_lang_ref_Reference, "pendingNext", "Ljava/lang/ref/Reference;"); if (!java_lang_ref_Reference_pendingNext) return FALSE; java_lang_ref_Reference_queue = rvmGetInstanceField(env, java_lang_ref_Reference, "queue", "Ljava/lang/ref/ReferenceQueue;"); if (!java_lang_ref_Reference_queue) return FALSE; java_lang_ref_Reference_queueNext = rvmGetInstanceField(env, java_lang_ref_Reference, "queueNext", "Ljava/lang/ref/Reference;"); if (!java_lang_ref_Reference_queueNext) return FALSE; java_lang_ref_PhantomReference = rvmFindClassUsingLoader(env, "java/lang/ref/PhantomReference", NULL); if (!java_lang_ref_PhantomReference) return FALSE; java_lang_ref_WeakReference = rvmFindClassUsingLoader(env, "java/lang/ref/WeakReference", NULL); if (!java_lang_ref_WeakReference) return FALSE; java_lang_ref_SoftReference = rvmFindClassUsingLoader(env, "java/lang/ref/SoftReference", NULL); if (!java_lang_ref_SoftReference) return FALSE; java_lang_ref_FinalizerReference = rvmFindClassUsingLoader(env, "java/lang/ref/FinalizerReference", NULL); if (!java_lang_ref_FinalizerReference) return FALSE; java_lang_ref_FinalizerReference_add = rvmGetClassMethod(env, java_lang_ref_FinalizerReference, "add", "(Ljava/lang/Object;)V"); if (!java_lang_ref_FinalizerReference_add) return FALSE; java_lang_ref_FinalizerReference_zombie = rvmGetInstanceField(env, java_lang_ref_FinalizerReference, "zombie", "Ljava/lang/Object;"); if (!java_lang_ref_FinalizerReference_zombie) return FALSE; java_lang_ref_ReferenceQueue = rvmFindClassUsingLoader(env, "java/lang/ref/ReferenceQueue", NULL); if (!java_lang_ref_ReferenceQueue) return FALSE; java_lang_ref_ReferenceQueue_add = rvmGetClassMethod(env, java_lang_ref_ReferenceQueue, "add", "(Ljava/lang/ref/Reference;)V"); if (!java_lang_ref_ReferenceQueue_add) return FALSE; java_nio_ReadWriteDirectByteBuffer = rvmFindClassUsingLoader(env, "java/nio/ReadWriteDirectByteBuffer", NULL); if (!java_nio_ReadWriteDirectByteBuffer) return FALSE; java_nio_ReadWriteDirectByteBuffer_init = rvmGetInstanceMethod(env, java_nio_ReadWriteDirectByteBuffer, "<init>", "(II)V"); if (!java_nio_ReadWriteDirectByteBuffer_init) return FALSE; Class* java_nio_Buffer = rvmFindClassUsingLoader(env, "java/nio/Buffer", NULL); if (!java_nio_Buffer) return FALSE; java_nio_Buffer_effectiveDirectAddress = rvmGetInstanceField(env, java_nio_Buffer, "effectiveDirectAddress", "I"); if (!java_nio_Buffer_effectiveDirectAddress) return FALSE; java_nio_Buffer_capacity = rvmGetInstanceField(env, java_nio_Buffer, "capacity", "I"); if (!java_nio_Buffer_capacity) return FALSE; // Make sure that java.lang.ReferenceQueue is initialized now to prevent deadlocks during finalization // when both holding the referentsLock and the classLock. rvmInitialize(env, java_lang_ref_ReferenceQueue); if (rvmExceptionOccurred(env)) return FALSE; return TRUE; }
static void initializeClass(Env* env, ClassInfoHeader* header) { Class* clazz = ldcClass(env, header); if (clazz) rvmInitialize(env, clazz); }
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(); }