You need to enable JavaScript to run this app. Android NDK读取存储值偶现为空 仅Android 5.1/6系统复现
优惠活动
大模型
产品
解决方案
定价
更多

Android NDK读取存储值偶现为空 仅Android 5.1/6系统复现

问题根因
  • 最核心的问题是JNI调用中字符串指针提前释放:你调用GetStringUTFChars获取到C字符串指针NativeUrlName后,立刻调用了ReleaseStringUTFChars释放该指针,之后再将已失效的野指针传入方法访问内存。这种未定义行为的表现和系统内存管理策略强相关:Android 7+的ART虚拟机对字符串内存的回收策略更保守,野指针大概率还能读到原始值,而Android 5.1/6的Dalvik/早期ART实现中,释放后的内存会被快速回收或复用,因此会随机出现读取空值、乱码甚至崩溃的问题。
  • 代码存在多处笔误:UrlHash类的getUrl方法参数为urlKey,实际访问的是不存在的变量debugUrlKey;JNI层调用的getDebugUrl方法在UrlHash类中未定义,实际应为getUrl。
  • 用std::unordered_map的operator[]查询值存在隐患:如果查询的key不存在,operator[]会自动插入一个空字符串的键值对,返回空值,也会导致偶发空结果。
修复方案

修正后的C++代码如下:

#include <jni.h>
#include <string>
#include <unordered_map>

class UrlHash {
    std::unordered_map<std::string, std::string> urlHash;
public:
    // 修正变量名笔误,改用find查询避免插入空值
    std::string getUrl(std::string urlKey) {
        auto iter = urlHash.find(urlKey);
        if (iter != urlHash.end()) {
            return iter->second;
        }
        return ""; // 不存在时可返回自定义默认值
    }

    UrlHash() {
        urlHash["dummy"] = "dumyValue";
        urlHash["dump_url"] = "https://dump.server.com";
        urlHash["dump_url2"] = "https://dump2.server.com";
    }
};

extern "C"
JNIEXPORT jstring JNICALL
Java_my_com_mynativecapp_UrlProvider_getUrl(JNIEnv *env, jobject thiz, jstring urlName) {
    UrlHash _debugHashtableInstance;
    const char *NativeUrlName = env->GetStringUTFChars(urlName, 0);
    // 先使用字符串,用完再释放
    std::string result = _debugHashtableInstance.getUrl(NativeUrlName);
    env->ReleaseStringUTFChars(urlName, NativeUrlName);
    return env->NewStringUTF(result.c_str());
}

如果UrlHash实例不需要每次调用都重建,可以改成静态实例减少构造开销,不影响核心逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 00:09:03