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; }
jint _bcInstanceof(Env* env, ClassInfoHeader* header, Object* o) { if (!o) return (jint) FALSE; ENTER; Class* clazz = ldcClass(env, header); jboolean b = FALSE; if (clazz) { b = rvmIsInstanceOf(env, o, clazz); } LEAVE((jint) b); }
jvalue* validateAndUnwrapArgs(Env* env, ObjectArray* parameterTypes, ObjectArray* args) { jint length = args->length; jvalue* jvalueArgs = length > 0 ? (jvalue*) rvmAllocateMemory(env, sizeof(jvalue) * length) : emptyJValueArgs; if (!jvalueArgs) return NULL; jint i; for (i = 0; i < length; i++) { Object* arg = args->values[i]; Class* type = (Class*) parameterTypes->values[i]; if (CLASS_IS_PRIMITIVE(type)) { if (arg == NULL) { const char* typeName = rvmGetHumanReadableClassName(env, type); if (typeName) { rvmThrowNewf(env, java_lang_IllegalArgumentException, "argument %d should have type %s, got null", i + 1, typeName); } return NULL; } if (!rvmUnbox(env, arg, type, &jvalueArgs[i])) { if (rvmExceptionOccurred(env)->clazz == java_lang_ClassCastException) { rvmExceptionClear(env); const char* argTypeName = rvmGetHumanReadableClassName(env, arg->clazz); const char* typeName = argTypeName ? rvmGetHumanReadableClassName(env, type) : NULL; if (argTypeName && typeName) { rvmThrowNewf(env, java_lang_IllegalArgumentException, "argument %d should have type %s, got %s", i + 1, typeName, argTypeName); } } return NULL; } } else { if (arg && !rvmIsInstanceOf(env, arg, type)) { const char* argTypeName = rvmGetHumanReadableClassName(env, arg->clazz); const char* typeName = argTypeName ? rvmGetHumanReadableClassName(env, type) : NULL; if (argTypeName && typeName) { rvmThrowNewf(env, java_lang_IllegalArgumentException, "argument %d should have type %s, got %s", i + 1, typeName, argTypeName); } return NULL; } jvalueArgs[i].l = (jobject) arg; } } return jvalueArgs; }
jint _bcInstanceofArray(Env* env, Class* arrayClass, Object* o) { if (!o) return (jint) FALSE; ENTER; jboolean b = rvmIsInstanceOf(env, o, arrayClass); LEAVE((jint) b); }
static jboolean IsInstanceOf(JNIEnv* env, jobject obj, jclass clazz) { return rvmIsInstanceOf((Env*) env, (Object*) obj, (Class*) clazz); }
jboolean Java_java_lang_Class_isInstance(Env* env, Class* thiz, Object* object) { return rvmIsInstanceOf(env, object, thiz); }
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(); }