Android的JNI tips页面提到了这个常见问题:为什么FindClass找不到我的类?他们提到了多种解决方案,最后一个选项是:
Cache a reference to the ClassLoader object somewhere handy, and issue loadClass calls directly. This requires some effort.
缓存对ClassLoader对象的引用,并直接发出loadClass调用。这需要一些努力。
So, I tried to get it working and it seems that no matter what, this method simply does not work for me. Eventually, I figured how to use ClassLoader but it won't work if from a native thread I try to loadClass that hasn't been touched/loaded yet. Essentially, it's the identical to env->FindClass in behavior when called from a native thread, with the exception that it won't return 0 for classes that were already use in the app. Any idea if I didn't get it right, or it's impossible to access classes from a native thread that weren't used/loaded yet.
所以,我试着让它起作用,似乎无论如何,这个方法对我都不起作用。最终,我找到了如何使用ClassLoader的方法,但如果我尝试从一个本地线程加载尚未被触摸/加载的类,那么它将无法工作。从本质上讲,它是相同的env - > FindClass当从一个本地调用线程的行为,除了它不会返回0类已经使用的应用程序。你知道如果我没有得到正确的,或从一个本地线程访问类是不可能的,不使用/加载。
EDIT: I'll give more info to explain what exactly I mean. There is regular JNI env->FindClass(className)
, and another one that I wrote myFindClass(env, className)
that uses cached ClassLoader->loadClass
.
编辑:我会提供更多的信息来解释我的意思。有常规的JNI env->FindClass(className),还有一个是我编写的myFindClass(env, className),使用缓存的ClassLoader——>loadClass。
The class that I'm trying to access from native c/c++ is "com/noname/TestClient". Inside myFindClass I also use env->FindClass and log value that it returns:
我正在尝试从本机c/c++中访问的类是com/ name/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));
- ...
- }
Then, I have these 3 combinations to explain the issue.
然后,我有这三个组合来解释这个问题。
1)
1)
- //inside JNI_OnLoad thread
- myFindClass(env, "com/noname/TestClient");
- ...
-
- //inside native thread created by pthread_create
- myFindClass(env, "com/noname/TestClient");
I get this logcat:
我得到这个logcat:
myFindClass("com/noname/TestClent") => c0:0x41b64558, c1:0x41b64558, c0 and c1 are same: 1
...
myFindClass("com/noname/TestClent") => c0:0, c1:0x41b64558, c0 and c1 are same: 0查查myFindClass(com/ noname/testclent) => c0:0x41b64558, c1:0x41b64558, c0和c1相同:1…查查查查myFindClass(com/noname/testclent) => c0:0, c1:0x41b64558, c0和c1相同:0
2)
2)
- //inside JNI_OnLoad thread
- env->FindClass("com/noname/TestClient");
- ...
-
- //inside native thread created by pthread_create
- myFindClass("com/noname/TestClient");
I get this logcat:
我得到这个logcat:
myFindClass("com/noname/TestClent") => c0:0, c1:0x41b64558, c0 and c1 are same: 0
查查查查myFindClass(com/noname/testclent) => c0:0, c1:0x41b64558, c0和c1相同:0
3)
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");
I get this logcat:
我得到这个logcat:
myFindClass("com/noname/TestClent") => c0:0, c1:0, c0 and c1 are same: 1
查查myFindClass(com/ noname/testclent”)=> c0:0, c1:0, c0和c1相同:1
Basically, my issue is that ClassLoader doesn't find my class in the 3rd case. Is it a bug? What can be done to fix the problem?
基本上,我的问题是ClassLoader不能在第三种情况下找到我的类。这是一个错误吗?我们能做些什么来解决这个问题呢?
EDIT2: On top of that, it seems that ClassLoader::loadClass is plainly buggy. If I ask myFindClass("noname/TestClent") then it returns some garbage, and when I use that returned jclass in any way the app crashes.
最重要的是,ClassLoader::loadClass显然存在bug。如果我问myFindClass(“noname/TestClent”),它会返回一些垃圾,当我使用返回的jclass时,应用程序会崩溃。