You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenXR API Layer动态库中JNI无法从外部AAR查找类

解决OpenXR API Layer中JNI查找AAR类失败的问题

核心问题本质

你碰到的ClassNotFoundException,根源是OpenXR Layer动态库的运行上下文类加载器,无法访问你引入的AAR对应的Dex文件。哪怕build.gradle已经配置依赖、dexdump验证类已加载,但OpenXR Layer作为独立动态库,其类加载器和主APP的类加载器并非完全共享,直接调用FindClass或用Native Activity的类加载器,都覆盖不到AAR的Dex路径。

可行解决方案

1. 主动传递主APP的ClassLoader到OpenXR Layer

既然没法干预JVM初始化流程,最直接的办法是从主APP Java层,把能加载mudraAndroidSDK.model.MudraDevice的ClassLoader传给Layer:

  • 在主APP的Activity(比如NativeActivity子类)中获取类加载器:
    ClassLoader appClassLoader = getApplicationContext().getClassLoader();
    
  • 通过JNI将这个ClassLoader对象保存为全局引用,或者借助OpenXR扩展机制直接传递给Layer(如果Layer支持自定义参数)。
  • 在OpenXR Layer的JNI代码中,用这个ClassLoader加载目标类:
    jclass classLoaderCls = env->GetObjectClass(classLoaderObj);
    jmethodID loadClassMethod = env->GetMethodID(classLoaderCls, "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;");
    jstring clsName = env->NewStringUTF("mudraAndroidSDK.model.MudraDevice");
    jclass targetCls = static_cast<jclass>(env->CallObjectMethod(classLoaderObj, loadClassMethod, clsName));
    // 清理局部引用
    env->DeleteLocalRef(clsName);
    env->DeleteLocalRef(classLoaderCls);
    

2. 强制将AAR类打包到主Dex

如果AAR体积不大,可以把目标类强制放到主Dex里,确保类加载器能直接找到:

  • 在build.gradle的android块中配置规则:
    android {
        buildTypes {
            debug {
                multiDexKeepProguard file('multiDexKeep.pro')
            }
            release {
                multiDexKeepProguard file('multiDexKeep.pro')
            }
        }
    }
    
  • 在同级目录的multiDexKeep.pro中添加:
    -keep class mudraAndroidSDK.model.MudraDevice { *; }
    
    这样打包时会把该类强制放入主Dex,避免被拆分到辅助Dex,Native层用FindClass就能直接定位。

3. 确认Layer的加载时机与进程上下文

OpenXR Layer可能在主APP完全初始化前就被加载,此时AAR的Dex还没被系统类加载器加载:

  • 在主APP的onCreate中主动触发AAR类的初始化(比如Class.forName("mudraAndroidSDK.model.MudraDevice")),再启动OpenXR相关逻辑。
  • 验证Layer是否在主APP进程运行,打印进程ID确认:
    __android_log_print(ANDROID_LOG_DEBUG, "XR_LAYER", "Current PID: %d", getpid());
    

验证排查手段

  • 用adb shell dumpsys package <你的包名>查看dexPaths列表,确认AAR的Dex是否在其中。
  • 在JNI代码中打印当前线程的上下文类加载器,对比主APP的类加载器:
    jclass threadCls = env->FindClass("java/lang/Thread");
    jmethodID getLoaderMethod = env->GetMethodID(threadCls, "getContextClassLoader", "()Ljava/lang/ClassLoader;");
    jobject contextLoader = env->CallObjectMethod(env->GetCurrentThread(), getLoaderMethod);
    
    jclass loaderCls = env->FindClass("java/lang/ClassLoader");
    jmethodID toStringMethod = env->GetMethodID(loaderCls, "toString", "()Ljava/lang/String;");
    jstring loaderStr = static_cast<jstring>(env->CallObjectMethod(contextLoader, toStringMethod));
    const char* loaderCStr = env->GetStringUTFChars(loaderStr, nullptr);
    __android_log_print(ANDROID_LOG_DEBUG, "XR_LAYER", "Current ClassLoader: %s", loaderCStr);
    
    // 清理引用
    env->ReleaseStringUTFChars(loaderStr, loaderCStr);
    env->DeleteLocalRef(loaderStr);
    env->DeleteLocalRef(loaderCls);
    env->DeleteLocalRef(contextLoader);
    env->DeleteLocalRef(threadCls);
    

内容的提问来源于stack exchange,提问作者Naor Liron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 18:45:01