【发布时间】:2021-10-02 11:14:07
【问题描述】:
目前库(.so)是使用 Visual Studio 构建的,并放置在 jniLibs 目录中。 如下图,
在 JNI 调用中查找类时遇到异常(这里是 TWMainActivity,但对于任何其他类都是如此),
2021-07-23 08:10:43.992 13617-1658/com.tally.twandroidconsolesimulator A/onsolesimulato: java_vm_ext.cc:578] JNI DETECTED ERROR IN APPLICATION: JNI GetMethodID called with pending exception java.lang.ClassNotFoundException: Didn't find class "com.tally.twandroidconsolesimulator.TWMainActivity" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /system/lib64]]
java_vm_ext.cc:578] at java.lang.Class dalvik.system.BaseDexClassLoader.findClass(java.lang.String) (BaseDexClassLoader.java:207)
java_vm_ext.cc:578] at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String, boolean) (ClassLoader.java:379)
java_vm_ext.cc:578] at java.lang.Class java.lang.ClassLoader.loadClass(java.lang.String) (ClassLoader.java:312)
java_vm_ext.cc:578]
java_vm_ext.cc:578] in call to GetMethodID
通过对通过 JNI 调用(java 到 C++)传递的对象的全局引用能够获得 jclass。
//this is working
jclass cls = env->GetObjectClass (sMainActivityGlobalRef);
//this is not working throwing mentioned exceptions
// jclass cls = env->FindClass ("com/tally/twandroidconsolesimulator/TWMainActivity");
注意:相同的代码在没有 jniLibs 的情况下与 Andrdoid Studio Native 项目一起工作
基本代码流程如下,
public class TWMainActivity extends AppCompatActivity {
static {
System.loadLibrary("TWXPControlsGalleryApp_arm64-v8a");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InitializeMain();
}
public native void InitializeMain();
}
//本机代码
static void
NativeThread(JavaVM * pJavaVm, jint pJVersion, jobject pObjGblRfrnc){
JNIEnv * env;
auto get_env_result = vm->GetEnv ((void **) &env, pJVersion);
if (get_env_result == JNI_EDETACHED) {
if (vm->AttachCurrentThread (env, nullptr) != JNI_OK) {
return;
}
}
jclass cls = env->FindClass ("com/tally/twandroidconsolesimulator/TWMainActivity");
//... rest of the code follows here
}
extern "C" JNIEXPORT void JNICALL
Java_com_tally_twandroidconsolesimulator_TWMainActivity_InitializeMain (JNIEnv * pEnv, jobject pObj)
{
JavaVM * sJavaVm;
jint jv_version = pEnv->GetVersion ();
pEnv->GetJavaVM (&sJavaVm);
jobject ref = pEnv->NewGlobalRef (pObj);
std::thread thread1 (NativeThread, sJavaVm, jv_version, ref );
thread1.detach ();
}
已转介this、this、this、this,但没有帮助解决问题。
环境:
classpath "com.android.tools.build:gradle:4.2.1"
感谢任何提示。
【问题讨论】:
-
你没有提供很多信息。例如,当您调用
FindClass时,您在哪个线程上?你读过developer.android.com/training/articles/… 吗? -
@Michael:我已经更新了基本的代码流程。 JNI 调用来自 C++/Native 线程,如图所示是代码
-
好的,因为您在本机线程上,所以您描述的行为是可以预料的。请参阅我链接到的页面以获取解释和可能的解决方案。
-
@Michael:当然谢谢。我会尝试在
JNI_OnLoad中加载课程。 -
@Michael:该解决方案正在 JNI_OnLoad 上运行 w.r.t 加载类。您可以在我接受的答案中添加相同的内容。再次感谢你:)
标签: java android java-native-interface