参考文章:《在 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. Python之路,第一篇:Python入门与基础

    第一篇:Python入门与基础 1,什么是python? Python 是一个高层次的结合了解释性.编译性.互动性和面向对象的脚本语言. 2,python的特征: (1)易于学习,易于利用: (2)开 ...

  2. JS中数据类型的判断

    typeof 使用 : var n = "hello"; console.log(typeof n); console.log(typeof(n));

  3. Gym - 101806R :Recipe(分治+斜率优化)

    题意:有一个厨师,他买菜-做菜-买菜-做菜....-做菜,一共有N天,他的冰箱里只能有一个菜,在他做菜的第二天才会买菜,如果菜不做,放在冰箱里,每天新鲜程度会下降1. 第一天也会买菜,第i天的菜新鲜程 ...

  4. Light OJ 1296:Again Stone Game(SG函数打表找规律)

    Alice and Bob are playing a stone game. Initially there are n piles of stones and each pile contains ...

  5. 2017.7.11 linux 挂载

    挂载:Liunx采用树形的文件管理系统,也就是在Linux系统中,可以说已经没有分区的概念了.分区在Linux和其他设备一样都只是一个文件.要使用一个分区必须把它加载到文件系统中.这可能难于理解,继续 ...

  6. Django项目的创建和设计模式

    1.安装django pip  install  django 2.创建项目 进入到项目文件夹的根目录下 django-admin   startproject    <project_name ...

  7. SQL Server 排序的时候使 null 值排在最后

    https://www.cnblogs.com/Brambling/p/7046148.html 最近遇到一个 SQL Server 排序的问题,以前也没了解过,然后这次碰到了. 才发现 SQL Se ...

  8. 【BZOJ3240】【UOJ#124】【NOI2013】矩阵游戏

    终于看懂一道题QAQ然而NOI都是这种难度题怎么玩QAQ 原题: 婷婷是个喜欢矩阵的小朋友,有一天她想用电脑生成一个巨大的n行m列的矩阵(你不用担心她如何存储).她生成的这个矩阵满足一个神奇的性质:若 ...

  9. 【HAOI2012】外星人

    又犯sb错了QAQ 原题: 艾莉欧在她的被子上发现了一个数字 ,她觉得只要找出最小的x使得,.根据这个 她就能找到曾经绑架她的外星人的线索了.当然,她是不会去算,请你帮助她算出最小的x. test&l ...

  10. Android.bp学习笔记

    1.Android.bp简介 Android 7.0之后希望用Android.bp替换Android.mk,bp简单的配置更方便Ninja 文件的产生,而Blueprint和Soong 就此产生.An ...