jboolean rvmThrowInternalErrorErrno(Env* env, int errnum) { char message[THROW_FORMAT_BUF_SIZE]; if (strerror_r(errnum, message, THROW_FORMAT_BUF_SIZE) == 0) { return rvmThrowNew(env, java_lang_InternalError, message); } else { return rvmThrowNew(env, java_lang_InternalError, NULL); } }
static void throwSocketExceptionErrno(Env* env, int errnum) { char message[512]; JClass* exCls = rvmFindClassUsingLoader(env, "java/net/SocketException", NULL); if (!exCls) { return; } if (strerror_r(errnum, message, 512) == 0) { rvmThrowNew(env, exCls, message); } else { rvmThrowNew(env, exCls, NULL); } }
jboolean rvmThrowNewf(Env* env, Class* clazz, const char* format, ...) { va_list ap; char message[THROW_FORMAT_BUF_SIZE]; va_start(ap, format); vsnprintf(message, THROW_FORMAT_BUF_SIZE, format, ap); va_end(ap); return rvmThrowNew(env, clazz, message); }
static Class* findType(Env* env, const char* classDesc, Object* loader) { Class* c = rvmFindClassByDescriptor(env, classDesc, loader); if (!c) { if (rvmExceptionOccurred(env)->clazz == java_lang_ClassNotFoundException) { rvmExceptionClear(env); char* className = rvmCopyMemoryAtomicZ(env, classDesc); className[strlen(className)] = 0; rvmThrowNew(env, java_lang_TypeNotPresentException, rvmFromBinaryClassName(env, &className[1])); } } return c; }
char* toBinaryName(Env* env, Object* className) { if (!className) { rvmThrowNew(env, java_lang_NullPointerException, "className"); return NULL; } char* classNameUTF = rvmGetStringUTFChars(env, className); if (!classNameUTF) return NULL; jint i; for (i = 0; classNameUTF[i] != '\0'; i++) { if (classNameUTF[i] == '.') classNameUTF[i] = '/'; } return classNameUTF; }
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 rvmThrowUnsatisfiedLinkError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_UnsatisfiedLinkError, ""); }
jboolean rvmThrowNegativeArraySizeException(Env* env) { return rvmThrowNew(env, java_lang_NegativeArraySizeException, ""); }
jboolean rvmThrowClassNotFoundException(Env* env, const char* className) { char* msg = rvmToBinaryClassName(env, className); if (!msg) return FALSE; return rvmThrowNew(env, java_lang_ClassNotFoundException, msg); }
jboolean rvmThrowNoClassDefFoundError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_NoClassDefFoundError, message); }
static void throwUnsupportedOperationException(Env* env, char* msg) { Class* clazz = rvmFindClassUsingLoader(env, "java/lang/UnsupportedOperationException", NULL); if (!clazz) return; rvmThrowNew(env, clazz, msg); }
jboolean rvmThrowNewfv(Env* env, Class* clazz, const char* format, va_list ap) { char message[THROW_FORMAT_BUF_SIZE]; vsnprintf(message, THROW_FORMAT_BUF_SIZE, format, ap); return rvmThrowNew(env, clazz, message); }
jboolean rvmThrowIllegalStateException(Env* env, const char* message) { return rvmThrowNew(env, java_lang_IllegalStateException, message); }
jboolean rvmThrowIncompatibleClassChangeErrorMethod(Env* env, Class* clazz, const char* name, const char* desc) { // TODO: Message should look like ? return rvmThrowNew(env, java_lang_IncompatibleClassChangeError, ""); }
jboolean rvmThrowIncompatibleClassChangeErrorInstanceField(Env* env, Class* clazz, const char* name, const char* desc) { // TODO: Message should look like "java.lang.ThrowIncompatibleClassChangeError: Expected non-static field a.C.x" return rvmThrowNew(env, java_lang_IncompatibleClassChangeError, ""); }
jboolean rvmThrowIncompatibleClassChangeError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_IncompatibleClassChangeError, message); }
jboolean rvmThrowNoSuchMethodError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_NoSuchMethodError, message); }
jboolean rvmThrowIllegalAccessError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_IllegalAccessError, message); }
jboolean rvmThrowLinkageError(Env* env) { return rvmThrowNew(env, java_lang_LinkageError, ""); }
jboolean rvmThrowArithmeticException(Env* env) { return rvmThrowNew(env, java_lang_ArithmeticException, NULL); }
jboolean rvmThrowInterruptedException(Env* env) { return rvmThrowNew(env, java_lang_InterruptedException, NULL); }
jboolean rvmThrowClassCastException(Env* env, Class* expectedClass, Class* actualClass) { // TODO: Message should look like "java.lang.ClassCastException: java.lang.Object cannot be cast to java.lang.String" return rvmThrowNew(env, java_lang_ClassCastException, ""); }
jboolean rvmThrowInstantiationError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_InstantiationError, message); }
static jboolean throwFormatError(Env* env, char* expectedType) { char msg[64]; snprintf(msg, sizeof(msg), "Invalid format: %s expected", expectedType); rvmThrowNew(env, java_lang_annotation_AnnotationFormatError, msg); return FALSE; }
static jint ThrowNew(JNIEnv* env, jclass clazz, const char* msg) { return rvmThrowNew((Env*) env, (Class*) clazz, msg) ? 0 : -1; }
jboolean rvmThrowArrayStoreException(Env* env) { return rvmThrowNew(env, java_lang_ArrayStoreException, ""); }
jboolean rvmThrowNullPointerException(Env* env) { return rvmThrowNew(env, java_lang_NullPointerException, NULL); }
jboolean rvmThrowOutOfMemoryError(Env* env) { return rvmThrowNew(env, java_lang_OutOfMemoryError, NULL); }
jboolean rvmThrowAbstractMethodError(Env* env, const char* message) { return rvmThrowNew(env, java_lang_AbstractMethodError, message); }
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(); }