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

Android JNI中从内存加载本地库遇加载失败问题求助

Android内存加载本地库失败排查与解决

问题描述

我正在做Android平台下从内存加载本地库的实验:通过syscall(SYS_memfd_create, "lib", 0)创建有效的memfd文件描述符,使用write()将ELF文件内容写入该描述符后,通过/proc/self/fd/%d路径调用System.load()加载库,出现错误:

java.lang.UnsatisfiedLinkError: dlopen failed: library "/proc/self/fd/76" not found
...

同时直接调用dlopen()加载该路径也返回NULL,dlerror提示相同信息。

相关代码:

int mem_lib_fd = syscall(SYS_memfd_create, "lib", 0);
DBG_LOG_VA("memfd_create(): %d", mem_lib_fd);
if (mem_lib_fd < 0)
    return -1;
sys_write(mem_lib_fd, elf_buf, elf.size);

char load_path[0xff];
sprintf(load_path, "/proc/self/fd/%d", mem_lib_fd);
DBG_LOG_VA("lib path: %s", load_path);

jclass jSystem = env->FindClass("java/lang/System");
jmethodID jSystem_load = env->GetStaticMethodID(jSystem, "load", "(Ljava/lang/String;)V");
env->CallStaticVoidMethod(jSystem, jSystem_load, env->NewStringUTF(load_path));

问题原因

  1. Android安全机制限制:dlopen(包括System.load底层依赖的dlopen)默认拦截/proc/self/fd/这类虚拟路径的加载请求,防止恶意加载临时文件。
  2. memfd权限与属性缺失:创建memfd时未设置允许密封和可执行权限,写入ELF后也未配置文件的可执行属性,导致加载时权限不足。
  3. 文件指针位置问题:写入ELF后文件指针停在末尾,dlopen读取时可能无法获取完整的ELF内容。

解决办法

1. 修正memfd创建参数

创建memfd时需添加MFD_ALLOW_SEALING(允许后续密封操作)和MFD_CLOEXEC(进程执行新程序时自动关闭fd,避免泄漏)标志:

int mem_lib_fd = syscall(SYS_memfd_create, "lib", MFD_ALLOW_SEALING | MFD_CLOEXEC);

2. 设置文件可执行权限

写入ELF内容后,通过fchmod给memfd添加可执行权限:

fchmod(mem_lib_fd, 0755);

3. 重置文件指针到开头

写入完成后将文件指针重置到起始位置,确保dlopen能读取完整ELF:

lseek(mem_lib_fd, 0, SEEK_SET);

4. 使用文件描述符直接加载(推荐)

Android 8.0及以上版本支持通过android_dlopen_ext直接加载文件描述符,绕过/proc/self/fd路径限制:

#include <android/dlext.h>

void* handle = android_dlopen_ext(mem_lib_fd, RTLD_NOW, nullptr, ANDROID_DL_OPEN_FD);
if (!handle) {
    DBG_LOG_VA("dlopen failed: %s", dlerror());
    return -1;
}

若需在Java层调用,可在Native层完成库加载后,通过JNI暴露方法给Java,无需走System.load。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 00:57:03