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

Android NDK执行.so文件返回退出码0但无执行效果如何解决

问题根因
  • 常规CMake编译生成的Android .so 是动态链接库,仅用于dlopen加载调用,默认没有可执行程序的加载头与入口配置,哪怕你实现了main函数也无法被exec系统调用直接加载执行。你看到的进程返回码0实际是加载失败直接退出的状态,main函数完全没有被调用,所以没有日志和文件输出。
  • 你的执行代码存在路径缺失问题:直接写exec mylib.so时,su的执行环境没有对应的库路径搜索配置,系统找不到对应文件,也会导致执行失败。
修复步骤

1. 修正编译配置

如果你需要以独立进程的方式执行逻辑,不要用add_library编译动态库,改为编译可执行PIE程序(Android 5.0+要求可执行文件必须是位置无关的PIE格式),CMake配置修改如下:

add_executable(mylib_exec your_source_file.c)

set_target_properties(mylib_exec PROPERTIES
    POSITION_INDEPENDENT_CODE ON
    LINK_FLAGS "-pie -rdynamic"
    # 若需要保留.so后缀可以加下面这行
    OUTPUT_NAME "mylib" SUFFIX ".so"
)

find_library(
        log-lib
        log )

target_link_libraries(
        mylib_exec
        ${log-lib} )

如果你需要保留动态库供应用内加载,同时支持直接执行,也可以保留原来的add_library配置,新增上面的add_executable配置生成两个产物即可。

2. 修正执行逻辑

首先把编译出的可执行文件推送到设备的可执行目录,赋予可执行权限:

adb push mylib.so /data/local/tmp/
adb shell chmod 755 /data/local/tmp/mylib.so

修改Java层的执行代码,补全绝对路径:

process = new ProcessBuilder(new String[]{"su", "-c", "exec /data/local/tmp/mylib.so"}).start();

3. 日志获取

  • 本地文件日志:执行完成后,需要用su权限读取/data/local/tmp/log.txt,该文件是root身份生成,普通应用默认没有读取权限。
  • Logcat日志:需要在C代码开头定义LOG_TAG才能正常过滤日志:
    #define LOG_TAG "MY_LIB_TEST"
    #include <android/log.h>
    
    执行后用adb命令过滤日志即可:
    adb logcat -s MY_LIB_TEST:*

4. 手动调试排查

你可以先在adb shell中手动执行命令,直接看报错信息:

adb shell
su
cd /data/local/tmp
./mylib.so

如果是依赖库缺失、权限不足、格式错误等问题,会直接在终端输出报错,方便快速定位。

可选方案:应用内加载执行

如果你不需要开独立进程跑逻辑,可以改为常规动态库加载调用的方式,不需要su权限:

  1. 在原有C代码中新增JNI导出函数:
#include <jni.h>

JNIEXPORT void JNICALL
Java_com_your_package_MainActivity_runMyLogic(JNIEnv *env, jobject thiz) {
    // 直接调用你的原有main逻辑
    main(0, NULL);
}
  1. Java层声明native方法,调用System.loadLibrary("mylib")加载so后直接调用该native方法即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 00:45:01