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

JNI中native层存储Java对象出现jobject失效崩溃该如何解决?

问题根因

JNI 规范中将引用分为三类:局部引用、全局引用、弱全局引用。你在 native 方法参数中拿到的 jobject 属于局部引用,它的生命周期仅局限于当前 native 方法的调用周期内:

  • native 方法返回后,局部引用会被自动标记为失效
  • JVM 的垃圾回收器不会感知 native 层是否还持有该局部引用的拷贝,会正常回收引用指向的 Java 对象
    你后续访问已经失效的引用、指向已经被回收的对象内存,就会触发 JVM 的访问冲突错误。
错误操作点

你直接将方法参数传入的局部引用 value 赋值给全局变量 car,没有将其转换为生命周期更长的引用类型,导致方法退出后全局变量存储的引用直接失效。

正确实现方案

需要将局部引用转换为全局引用,全局引用跨 native 方法调用、跨线程有效,且会阻止 JVM 回收指向的 Java 对象,直到你手动释放该引用。
修改后的 com_gabrik_gabos_Main.cpp 代码如下:

#include "pch.h"
#include "com_gabrik_gabos_Main.h"

jobject car = nullptr;

JNIEXPORT void JNICALL Java_com_gabrik_gabos_Main_saveCar
(JNIEnv* env, jclass cls, jobject value) {
    // 先释放之前存储的旧全局引用,避免内存泄漏
    if (car != nullptr) {
        env->DeleteGlobalRef(car);
        car = nullptr;
    }
    // 将局部引用转换为全局引用后再存储
    car = env->NewGlobalRef(value);
}

JNIEXPORT jobject JNICALL Java_com_gabrik_gabos_Main_getSavedCar
(JNIEnv* env, jclass cls) {
    return car;
}

注意事项

  • 当你后续不再需要存储的 Car 对象时,必须主动调用 env->DeleteGlobalRef(car) 释放全局引用,否则该对象永远不会被 JVM 回收,会造成内存泄漏
  • 如果不需要阻止对象被 GC 回收,仅需要判断对象是否存活,可以选择使用 NewWeakGlobalRef 创建弱全局引用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 06:36:03