void* _bcLookupInterfaceMethodImpl(Env* env, ClassInfoHeader* header, Object* thiz, uint32_t index) { TypeInfo* typeInfo = header->typeInfo; ITables* itables = thiz->clazz->itables; ITable* itable = itables->cache; if (itable->typeInfo == typeInfo) { return itable->table.table[index]; } uint32_t i; for (i = 0; i < itables->count; i++) { itable = itables->table[i]; if (itable->typeInfo == typeInfo) { itables->cache = itable; return itable->table.table[index]; } } ENTER; initializeClass(env, header); Class* ownerInterface = header->clazz; 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); LEAVE(NULL); }
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; }
Class* rvmFindClassUsingLoader(Env* env, const char* className, ClassLoader* classLoader) { if (!classLoader || classLoader->parent == NULL) { // This is the bootstrap classloader. No need to call ClassLoader.loadClass() return findBootClass(env, className); } char* binaryClassName = rvmToBinaryClassName(env, className); if (!binaryClassName) return NULL; Object* binaryClassNameString = rvmNewInternedStringUTF(env, binaryClassName, -1); if (!binaryClassNameString) return NULL; Method* loadClassMethod = rvmGetInstanceMethod(env, java_lang_ClassLoader, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;"); if (!loadClassMethod) return NULL; Object* clazz = rvmCallObjectInstanceMethod(env, (Object*) classLoader, loadClassMethod, binaryClassNameString); if (rvmExceptionOccurred(env)) return NULL; return (Class*) clazz; }
void* rvmResolveNativeMethodImpl(Env* env, NativeMethod* method, const char* shortMangledName, const char* longMangledName, ClassLoader* classLoader, void** ptr) { void* f = method->nativeImpl; if (!f) { DynamicLib* nativeLibs = NULL; if (!classLoader || classLoader->parent == NULL) { // This is the bootstrap classloader nativeLibs = bootNativeLibs; } else if (classLoader->parent->parent == NULL && classLoader->object.clazz->classLoader == NULL) { // This is the system classloader nativeLibs = mainNativeLibs; } else { // Unknown classloader rvmThrowUnsatisfiedLinkError(env, "Unknown classloader"); return NULL; } obtainNativeLibsLock(); TRACEF("Searching for native method using short name: %s", shortMangledName); f = rvmFindDynamicLibSymbol(env, nativeLibs, shortMangledName, TRUE); if (f) { TRACEF("Found native method using short name: %s", shortMangledName); } else if (strcmp(shortMangledName, longMangledName)) { TRACEF("Searching for native method using long name: %s", longMangledName); f = rvmFindDynamicLibSymbol(env, nativeLibs, longMangledName, TRUE); if (f) { TRACEF("Found native method using long name: %s", longMangledName); } } method->nativeImpl = f; releaseNativeLibsLock(); } if (!f) { char* className = rvmToBinaryClassName(env, method->method.clazz->name); if (className) { rvmThrowNewf(env, java_lang_UnsatisfiedLinkError, "%s.%s%s", className, method->method.name, method->method.desc); } return NULL; } // TODO: Remember ptr to allow it to be reset when the JNI RegisterNatives/UnregisterNatives functions are called *ptr = f; return f; }
jboolean rvmThrowClassNotFoundException(Env* env, const char* className) { char* msg = rvmToBinaryClassName(env, className); if (!msg) return FALSE; return rvmThrowNew(env, java_lang_ClassNotFoundException, msg); }