JNI 错误:访问过时的弱全局引用

2024-03-02

我在本机代码中缓存了对 Java 对象的引用,如下所示:

// java global reference deleter
// _JAVA_ENV  is an instance of JNIEnv that is cached globally and just
// valid in current thread scope
static void g_java_ref_deleter(jobject ptr) {
   _JAVA_ENV->DeleteGlobalRef(ptr);
}

// native class caches a java object reference
class NativeA {
private:
    shared_ptr<_jobject> M_java_object;
public:
    setJavaObject(jobject obj) {
        M_java_object = shared_ptr<_jobject>(_JAVA_ENV->NewGlobalRef(obj), g_java_ref_deleter);
    }

    shared_ptr<_jobject> getJavaObject() const {
        return M_java_object;
    }
}

我在另一个本机类中访问它:

class NativeB {
public:
    void doSomething(NativeA& a) {
        // here I got an error: accessed stale weak global reference
        // make_record do something on java object (set float field actually)
        make_record(a.getJavaObject().get());
    }
}

此代码运行在 Android 4.3 上。为什么会出现此错误以及如何修复它?


好的,我已经解决了这个问题!其实我缓存了_JAVA_ENV并错误地使用它。由此blog http://android-developers.blogspot.com/2011/11/jni-local-reference-changes-in-ics.html我发现 :

尽管任何给定的 JNIEnv* 只能在一个线程上使用,但由于 Android 在 JNIEnv* 中从未有任何每线程状态,因此过去可以在错误的线程上使用 JNIEnv*。现在有一个每线程本地引用表,仅在正确的线程上使用 JNIEnv* 至关重要。

所以我认为我缓存没有问题JNIEnv并在一个线程中使用它,但实际上JNIEnv当程序进入java环境并返回到本机环境时就已经过时了。 (呃...原谅我糟糕的英语)

并从文档 http://developer.android.com/training/articles/perf-jni.html, 我发现 :

如果一段代码没有其他方法来获取其 JNIEnv,则应该共享 JavaVM,并使用 GetEnv 来发现线程的 JNIEnv。

因此,您应该缓存 JavaVM,并使用它来获取JNIEnv,代码如下:

JavaVM* g_jvm;

jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
    g_jvm = vm;
    JNIEnv* env;
    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
        return -1;
    }

    // Get jclass with env->FindClass.
    // Register methods with env->RegisterNatives.

    return JNI_VERSION_1_6;
}

JNIEnv* getJNIEnv() {
    JNIEnv* env;
    g_jvm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6 /*version*/);
    return env;
}

希望可以帮助别人! (请再次原谅我糟糕的英语..)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JNI 错误:访问过时的弱全局引用 的相关文章

  • 你的CPU不支持NX

    我刚刚下载了 android studio 但是我遇到了一个问题 当我运行它时 它说你的 cpu 不支持 NX 我应该怎么办 NX 或实际上是 NX 处理器位 是处理器的一项功能 有助于保护您的 PC 免受恶意软件的攻击 当此功能未启用并且
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 我想实现下面的布局,按钮应该在屏幕底部,当惰性列被填充时,按钮不应该出去

    顶部有惰性列 惰性列下方有输入电话号码布局并从电话簿布局添加联系人 我希望当未添加联系人时此布局位于顶部 当我添加大量联系人时输入电话号码并添加电话簿布局中的联系人会随着惰性列滚动并移出屏幕 我不让他们走出屏幕 当接触较多时 它们必须粘在底
  • 错误:在根项目“projectName”中找不到项目“app”

    我有一个在 Eclipse 中开发的旧应用程序 现在尝试将其迁移到 Android Studio 我更新了库并遵循了基本步骤 现在 我收到此错误 Error Project app not found in root project pro
  • 使用Caliper时如何指定命令行?

    我发现 Google 的微型基准测试项目 Caliper 非常有趣 但文档仍然 除了一些示例 完全不存在 我有两种不同的情况 需要影响 JVM Caliper 启动的命令行 我需要设置一些固定 最好在几个固定值之间交替 D 参数 我需要指定
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • Android访问远程SQL数据库

    我可以直接从 Android 程序访问远程 SQL 数据库 在网络服务器上 吗 即简单地打开包含所有必需参数的连接 然后执行 SQL 查询 这是一个私人程序 不对公众开放 仅在指定的手机上可用 因此我不担心第三方获得数据库访问权限 如果是这
  • Android向menuItem添加子菜单,addSubMenu()在哪里?

    我想根据我的参数以编程方式将 OptionsMenu 内的子菜单添加到 menuItem 中 我检查了android sdk中的 MenuItem 没有addSubMenu 方法 尽管你可以找到 hasSubMenu 和 getSubMen
  • Java列表的线程安全

    我有一个列表 它将在线程安全上下文或非线程安全上下文中使用 究竟会是哪一个 无法提前确定 在这种特殊情况下 每当列表进入非线程安全上下文时 我都会使用它来包装它 Collections synchronizedList 但如果不进入非线程安
  • 如何根据 gradle 风格设置变量

    我想传递一个变量test我为每种风格设置了不同的值作为 NDK 的定义 但出于某种原因 他总是忽略了最后味道的价值 这是 build gradle apply plugin com android library def test andr
  • Android 套接字和 asynctask

    我即将开始制作一个应该充当 tcp 聊天客户端的应用程序 我一直在阅读和阅读 我得出的结论是最好 如果不需要 将我的套接字和异步任务中的阅读器 问题是我不确定从哪里开始 因为我是 Android 新手 这至少对我来说是一项艰巨的任务 但据我
  • Android:膨胀布局时出现 StackOverFlowError 和 InvokingTargetException

    首先 对不起我的英语 我在膨胀布局时有一个问题 我有一个自定义视图 从 LinearLayout 扩展而来 称为按钮帮助 我在名为的布局上使用该视图加载活动 我的以下代码在所有设备和模拟器上都能完美运行 但具有 QVGA 屏幕 例如 Sam
  • 实现滚动选择 ListView 中的项目

    我想使用 ListView 您可以在其中滚动列表来选择一个项目 它应该像一个 Seekbar 但拇指应该是固定的 并且您必须使用该栏来调整它 我面临的一个问题是 我不知道这种小部件是如何调用的 这使得我很难搜索 所以我制作了下面这张图片 以
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 将 Intent 包装在 LabeledIntent 中以用于显示目的

    要求 我的应用程序中有一个 共享 按钮 我需要通过 Facebook 分享 我需要选择是否安装原生 Facebook 应用程序 我们的决定是 如果未安装该应用程序 则将用户发送到 facebook com 进行分享 当前状态 我可以检测何时
  • 有没有办法为Java的字符集名称添加别名

    我收到一个异常 埋藏在第 3 方库中 消息如下 java io UnsupportedEncodingException BIG 5 我认为发生这种情况是因为 Java 没有定义这个名称java nio charset Charset Ch
  • 如何将 google+ 登录集成到我的 Android 应用程序中?

    大家好 实际上我需要通过我的应用程序从 google 登录人们 现在我阅读了 google 上的文档 其中指出 要允许用户登录 请将 Google Sign In 集成到您的应用中 初始化 GoogleApiClient 对象时 请求 PL
  • 如何实现仅当可用内存较低时才将数据交换到磁盘的写缓存

    我想将应用程序生成的数据缓存在内存中 但如果内存变得稀缺 我想将数据交换到磁盘 理想情况下 我希望虚拟机通知它需要内存并将我的数据写入磁盘并以这种方式释放一些内存 但我没有看到任何方法以通知我的方式将自己挂接到虚拟机中before an O

随机推荐