【问题标题】:java.lang.ClassNotFoundException: on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib64, /system/lib64]]java.lang.ClassNotFoundException:在路径上:DexPathList [[目录“。”],nativeLibraryDirectories = [/system/lib64,/system/lib64]]
【发布时间】: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 ();
}

已转介thisthisthisthis,但没有帮助解决问题。

环境:

    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


【解决方案1】:

FindClass 如果在纯本机线程上调用,由于使用了错误的类加载器,将无法找到任何特定于应用程序的类。有关详细信息,请参阅 Android 开发人员文档中的 this section

有多种方法可以解决这个问题,但最简单的方法可能是解析 JNI_OnLoad 中的所有类,创建对它们的全局引用,并将这些全局引用保存在其余代码可以访问它们的地方。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-25
    • 2018-07-27
    • 2014-04-19
    • 1970-01-01
    • 1970-01-01
    • 2017-03-16
    • 2017-12-23
    相关资源
    最近更新 更多