【发布时间】:2012-11-07 04:56:51
【问题描述】:
Android 的 JNI 提示页面提到了这个FAQ: Why didn't FindClass find my class? 他们提到了多种解决方案,最后一个选项是这个:
在方便的地方缓存对 ClassLoader 对象的引用,然后发出 loadClass 直接调用。这需要一些努力。
所以,我试图让它工作,但似乎无论如何,这种方法对我来说根本不起作用。最终,我想出了如何使用 ClassLoader 但如果我从本机线程尝试加载尚未触摸/加载的类,它将无法工作。本质上,它在从本机线程调用时的行为与 env->FindClass 相同,只是它不会为应用程序中已使用的类返回 0。任何想法,如果我没有做对,或者不可能从尚未使用/加载的本机线程访问类。
编辑:我将提供更多信息来解释我的意思。有常规的 JNI env->FindClass(className),还有一个我写的 myFindClass(env, className) 使用缓存的 ClassLoader->loadClass。
我试图从本机 c/c++ 访问的类是“com/noname/TestClient”。在 myFindClass 中,我还使用 env->FindClass 并记录它返回的值:
jclass myFindClass(JNIEnv * env, const char* name)
{
...
jclass c0 = env->FindClass(name);
jclass c1 = (jclass)env->CallObjectMethod(ClassLoader,
MID_loadClass, envNewStringUTF(name));
dlog("myFindClass(\"%s\") => c0:%p, c1:%p, c0 and c1 are same: %d",
name, c0, c1, env->IsSameObject(c0, c1));
...
}
那么,我有这 3 个组合来解释这个问题。
1)
//inside JNI_OnLoad thread
myFindClass(env, "com/noname/TestClient");
...
//inside native thread created by pthread_create
myFindClass(env, "com/noname/TestClient");
我得到了这个 logcat:
myFindClass("com/noname/TestClent") => c0:0x41b64558, c1:0x41b64558, c0 和 c1 相同:1
...
myFindClass("com/noname/TestClent") => c0:0, c1:0x41b64558,c0和c1相同:0
2)
//inside JNI_OnLoad thread
env->FindClass("com/noname/TestClient");
...
//inside native thread created by pthread_create
myFindClass("com/noname/TestClient");
我得到了这个 logcat:
myFindClass("com/noname/TestClent") => c0:0, c1:0x41b64558, c0 和 c1 相同:0
3)
//inside JNI_OnLoad thread
//"com/noname/TestClient" isn't touched from JNI_OnLoad.
...
//inside native thread created by pthread_create
myFindClass(env, "com/noname/TestClient");
我得到了这个 logcat:
myFindClass("com/noname/TestClent") => c0:0, c1:0, c0 和 c1 相同:1
基本上,我的问题是 ClassLoader 在第三种情况下找不到我的课程。它是一个错误吗?有什么办法可以解决这个问题?
EDIT2: 最重要的是,似乎 ClassLoader::loadClass 显然是错误的。如果我问 myFindClass("noname/TestClent") 那么它会返回一些垃圾,当我以任何方式使用返回的 jclass 时,应用程序就会崩溃。
【问题讨论】:
-
是的,这很正常,Android 应用默认不使用系统类加载器。只需将您需要的所有内容缓存在
JNI_OnLoad()中即可。 -
Re: EDIT2: 听起来该方法抛出了异常,此时返回值未定义。
loadClass()从不返回 null;它要么返回类引用,要么抛出异常。 -
@fadden 可能是这样。我不记得到底是什么问题,但我最终解决了。
标签: android c++ java-native-interface