参考文章:《在 JNI 编程中避免内存泄漏

1 Local Reference 深层解析

  JNI Local Reference 的生命期是在 native method 的执行期(从 Java 程序切换到 native code 环境时开始创建,或者在 native method 执行时调用 JNI function 创建),在 native method 执行完毕切换回 Java 程序时,所有 JNI Local Reference 被删除,生命期结束(调用 JNI function 可以提前结束其生命期)。

  (我们实际编码中经常会自己封装一个NewStringUTF、NewObject之类的引用方法,在同一个nativeMethod中反复多次调用,其实这样是误以为LocalReference与局部变量的生命周期一致了)  

  实际上,每当线程从 Java 环境切换到 native code 上下文时(J2N),JVM 会分配一块内存,创建一个 Local Reference 表,这个表用来存放本次 native method 执行中创建的所有的 Local Reference。每当在 native code 中引用到一个 Java 对象时,JVM 就会在这个表中创建一个 Local Reference。比如,下面代码中我们调用 NewStringUTF() 在 Java Heap 中创建一个 String 对象后,在 Local Reference 表中就会相应新增一个 Local Reference。

Java 代码部分
class TestLocalReference {
private native void nativeMethod(int i);
public static void main(String args[]) {
TestLocalReference c = new TestLocalReference();
//call the jni native method
c.nativeMethod(1000000);
}
static {
//load the jni library
System.loadLibrary("StaticMethodCall");
}
} JNI 代码,nativeMethod(int i) 的 C 语言实现
#include<stdio.h>
#include<jni.h>
#include"TestLocalReference.h"
JNIEXPORT void JNICALL Java_TestLocalReference_nativeMethod
(JNIEnv * env, jobject obj, jint count)
{
jint i = 0;
jstring str; for(; i<count; i++)
str = (*env)->NewStringUTF(env, "0");
} 运行结果
JVMCI161: FATAL ERROR in native method: Out of memory when expanding
local ref table beyond capacity
at TestLocalReference.nativeMethod(Native Method)
at TestLocalReference.main(TestLocalReference.java:9)

图中说明:

⑴ 运行 native method 的线程的堆栈记录着 Local Reference 表的内存位置(指针 p)。

⑵ Local Reference 表中存放 JNI Local Reference,实现 Local Reference 到 Java 对象的映射。

⑶ native method 代码间接访问 Java 对象(java obj1,java obj2)。通过指针 p 定位相应的 Local Reference 的位置,然后通过相应的 Local Reference 映射到 Java 对象。

⑷ 当 native method 引用一个 Java 对象时,会在 Local Reference 表中创建一个新 Local Reference。在 Local Reference 结构中写入内容,实现 Local Reference 到 Java 对象的映射。

⑸ native method 调用 DeleteLocalRef() 释放某个 JNI Local Reference 时,首先通过指针 p 定位相应的 Local Reference 在 Local Ref 表中的位置,然后从 Local Ref 表中删除该 Local Reference,也就取消了对相应 Java 对象的引用(Ref count 减 1)。

⑹ 当越来越多的 Local Reference 被创建,这些 Local Reference 会在 Local Ref 表中占据越来越多内存。当 Local Reference 太多以至于 Local Ref 表的空间被用光,JVM 会抛出异常,从而导致 JVM 的崩溃。

2 关于JNI局部引用的释放

对于FindClass 返回的一定需要调用DeleteLocalRef,还有jbyteArray 类型的变量需要DeleteLocalRef。NewString / NewStringUTF / NewObject / GetObjectField生成的需要DeleteLocalRef。以上返回的类型变量是malloc出来的,不是栈变量。出作用域不会被释放,需要手动。

[Android] JNI中的Local Reference的更多相关文章

  1. ZT ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01

    ANDROID jni 中的事件回调机制JNIenv的使用 2012-09-10 12:53:01 分类: 嵌入式 android framework 里java调用native,使用JNI机制,ja ...

  2. Android NDK开发篇:如何使用JNI中的global reference和local reference

    JNI提供了一些实例和数组类型(jobject.jclass.jstring.jarray等)作为不透明的引用供本地代码使用.本地代码永远不会直接操作引用指向的VM内部的数据内容.要进行这些操作,必须 ...

  3. Android jni中回调java的方法

    在上一篇的基础上,添加在C++代码中回调java方法. 代码如下: Demo.java 中添加callback函数, 打印一条log. package com.example.scarecrow.dy ...

  4. Android JNI中C和JAVA代码之间的互相调用

    关于Android studio中使用NDK/JNI环境和入门:http://blog.csdn.net/quan648997767/article/details/64923143 1. C代码回调 ...

  5. Android JNI中C调用Java方法

    背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...

  6. Android JNI中的数据传递

    1.JNI 基本类型 当 Java 代码与本地代码 C/C++ 代码相互调用时,肯定会有参数的传递.两者属于不同的语言,数据类型有差别,此时,JNI 要保证两种语言之间的数据类型和数据空间大小的匹配. ...

  7. Cygwin的安装及在Android jni中的简单使用举例

    Cygwin是一个在windows平台上执行的类UNIX模拟环境,是cygnussolutions公司开发的自由软件.Cygwin是很多自由软件的集合,Cygwin的主要目的是通过又一次编译.将POS ...

  8. JNI中的内存管理(转)

    源:JNI中的内存管理 JNI 编程简介 JNI,Java Native Interface,是 native code 的编程接口.JNI 使 Java 代码程序可以与 native code 交互 ...

  9. [转]ANDROID JNI之JAVA域与c域的互操作

    本文讲述AndroidJava域与C域互操作:Java域调用c域的函数:c域访问Java域的属性和方法:c域生成的对象的保存与使用.重点讲解c域如何访问Java域. 虽然AndroidJNI实现中,c ...

随机推荐

  1. 【转载】 详解BN(Batch Normalization)算法

    原文地址: http://blog.csdn.net/hjimce/article/details/50866313 作者:hjimce ------------------------------- ...

  2. Gym - 101002K:YATP (树分治+二分+斜率优化)

    题意:给定带点权边权的树,定义路径的花费=路径边权和e+起点点权w[s]*终点点权w[t].N<2e5,e,w<1e6: 思路:首先,需要树分治. 然后得到方程dp[i]=min{ dis ...

  3. java实现图片上传功能,并返回图片保存路径

    1.前端html <div class="form-group">     <label for="inputPassword3" class ...

  4. Oracle中nvl()、instr()、及执行多条sql事务操作

    Oracle的Nvl函数 nvl( ) 函数 从两个表达式返回一个非null 值. 语法 NVL(eExpression1, eExpression2) 参数 eExpression1, eExpre ...

  5. Blender Tutorial - Earth curves [Animation nodes]笔记

    https://www.youtube.com/watch?v=jEYI4lnOprY&t= Blender Tutorial - Earth curves [Animation nodes] ...

  6. 《DSP using MATLAB》Problem 6.24

    代码: %% ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ %% Output In ...

  7. 【BZOJ4720】【NOIP2016】换教室

    我当年真是naive…… 原题: 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程.在可以选择的课程中,有2n节 课程安排在n个时间段上.在第i(1≤i≤n)个时间段上,两节 ...

  8. day 49 html 学习 css 学习

    画圆 <style> div{width: 100px; height:100px; border: solid red 3px; /*当弧度为.圆角半径为30时 得到的图像*/ bord ...

  9. 你不知道的JavaScript(下卷) (Kyle Simpson 著)

    第一部分 起步上路 第1章 深入编程 1.1 代码 1.2 表达式 1.3 实践 1.3.1 输出 1.3.2 输入 1.4 运算符 1.5 值与类型 1.6 代码注释 1.7 变量 1.8 块 1. ...

  10. 关于导出csv格式文件的身份证号、日期的处理

    EXCEL系统的单元格,默认格式是常规或数值格式下,数字超过10位即以科学计数法显示,对15位以后的数字用0填充. 在导入到Excel.导出csv文件时,对于身份证号自动变成科学计数法的地方,就要做一 ...