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

Android JNI调用Java内部类异常及构建耗时优化求助

问题1:Invokeclass无法执行 & 方法重复调用的解决办法

首先说下invokeclass()完全跑不起来的问题——你的JNI代码里有两个关键错误,直接导致JVM找不到这个方法,或者找不到目标内部类:

1. 修复Invokeclass的JNI实现

  • 函数签名不匹配:Java里的invokeclass()是非静态native方法,对应的JNI函数必须接收JNIEnv*和jobject两个参数,但你现在的C++代码里只写了JNIEnv *env,这会让JVM找不到对应的native实现,自然没法执行。
  • 内部类查找路径错了:Java的静态内部类bar在字节码中的完整类名是com/manvish/bwssb/Activities/MainActivity$bar(用$分隔外部类和内部类),你直接FindClass("bar")肯定找不到这个类啊。

修正后的invokeclass代码应该是这样的:

extern "C" JNIEXPORT jint JNICALL Java_com_manvish_bwssb_Activities_MainActivity_invokeclass(
        JNIEnv *env, jobject thiz) { // 补上漏掉的jobject参数
    // 用正确的内部类全路径查找
    jclass barClass = env->FindClass("com/manvish/bwssb/Activities/MainActivity$bar");
    if (barClass == nullptr) {
        __android_log_print(ANDROID_LOG_ERROR, "Gajanand", "找不到bar内部类");
        return -1;
    }
    // 获取静态方法ID,方法签名是对的,没问题
    jmethodID timesTenMid = env->GetStaticMethodID(barClass, "timesTen", "(I)I");
    if (timesTenMid == nullptr) {
        __android_log_print(ANDROID_LOG_ERROR, "Gajanand", "找不到timesTen方法");
        env->DeleteLocalRef(barClass); // 记得释放局部引用,避免内存泄漏
        return -1;
    }
    jint result = env->CallStaticIntMethod(barClass, timesTenMid, (jint)10);
    env->DeleteLocalRef(barClass);
    return result;
}

2. 解决方法重复调用的问题

看你Java代码的onCreate方法:

Toast.makeText(this, "" + stringFromJNI(), Toast.LENGTH_SHORT).show();
checkAES();
checkRSA();
invokeclass();
Log.d("Gajanand", "onCreate: "+invokeclass()); // 这里又调用了一次invokeclass()!

这里checkAES()和checkRSA()各被调用1次,但invokeclass()被调用了2次——一次单独调用,一次在Log的参数里。如果你觉得checkAES/checkRSA被重复调用,可能是之前JNI错误导致Activity重启?或者是日志打印的误解?先把invokeclass的问题修复后,去掉其中一次invokeclass()调用,就能避免重复执行了。


问题2:构建耗时超3分钟的优化方案

你的项目引入了OpenSSL,这是构建慢的核心原因——每次构建都要编译原生的OpenSSL源码,非常耗时。可以从这几个方向优化:

  1. 开启增量编译与代码优化
    在app/build.gradle里配置NDK和CMake的优化参数,减少重复编译的工作量:
android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                arguments "-DCMAKE_BUILD_TYPE=Release", "-DANDROID_STL=c++_shared"
                cppFlags "-O2" // 开启编译优化,既快又能减小产物体积
            }
        }
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a' // 只编译你需要的架构,去掉x86这些没用的
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.22.1" // 用稳定的CMake版本,避免兼容性问题
        }
    }
    buildFeatures {
        prefab true // 如果用Prefab管理OpenSSL,必须开这个
    }
}
  1. 改用预编译的OpenSSL库
    别再自己编译OpenSSL源码了!Android官方提供了Prefab分发的预编译OpenSSL库,直接在build.gradle里加依赖就行:
dependencies {
    implementation 'com.android.ndk.thirdparty:openssl:1.1.1s-beta1'
}

这样能跳过源码编译的巨大工作量,构建时间会大幅缩短。

  1. 启用Gradle缓存
    确保Android Studio里的Gradle缓存是开启的(默认开着),路径是Settings -> Build, Execution, Deployment -> Build Tools -> Gradle,勾选Build cache。这样相同的代码不会重复编译,依赖也不会重复下载。

内容的提问来源于stack exchange,提问作者Gajanand Swamy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:41:01