Jni里的内存管理

作者: 棒槌爸爸 | 来源:发表于2018-07-21 23:40 被阅读0次

名词解释:

JNI是什么:JNI是Java Native Interface的缩写,提供了若干API实现了Java和其他语言的通信(主要是C&C++)。

为什么要用JNI:在C/C++中写的程序可以避开JVM的内存开销过大的限制、处理高性能的计算、调用系统服务(例如驱动)等功能。

JVM:jvm是java虚拟机在jni层的代表,全局只有一个。

JNIENV:代表了java在本线程的运行环境,每个线程都有一个。

JOBJECT:在JNI中除了基本类型数组、Class、String和Throwable外其余所有Java对象的数据类型在JNI中都用jobject表示

JNI工作原理:

如图:

1. java层调用system.load方法。

2. 通过classloader拿到了so的绝对路径,然后调用nativeload()方法。

3. 通过linux下的dlopen方法,加载并查找so库里的方法,如有jni_onload会优先加载。

4. 当前线程下的jnienv会将所有的jni方法注册到了同一个vm中,so和class到了同一个进程空间。

5. 通过当前线程的jnienv即可调用对应的对象方法了。  

为什么要在JNI层缓存ID:

先看一张native方法和java方法的调用同样方法的耗时统计图,可以看到,2者耗时差距为11倍。

设备native首次native 1万次java首次java一万次

荣耀3X0.0410.560.021.17

NOTE30.033.020.0090.04

NOTE40.073.560.060.19

NEXUS50.073.440.020.35

NEXUS60.204.120.030.40

平均0.0824.960.0270.43

倍数3.011.5

原因:

C++调用java需要查找类,查找方法,查找方法ID,获取字段或者方法的调用有时候会需要在JVM中完成大量工作,因为字段和方法可能是从超类中继承而来的,为特定类返回的id不会在Jvm进程生存期间发生变化 ,这会让jvm向上遍历类层次结构来找到它们,这是个开销很大的操作。

所以,缓存ID字段是为了降低CPU负载,提高运行速度,节约电量。

JNI里的缓存类型:

Global Reference:全局引用生存周期为创建后,直到程序员显示的释放它,否则一直存在。

全局引用可以在多线程之间共享其指向的对象。

Local Reference : 局部引用生存周期为创建后,直到DeleteLocalRef . 或在该方法结束后没有被JVM发现有JAVA层引用而被JVM回收并释放。

局部引用只对当前线程有效,多个线程间不能共享局部引用。

注意:

基于谁创建谁销毁的原则,native函数执行完后,局部引用没有被native代码显示删除,那么局部引用在JVM中还是有效的,JVM决定什么时候删除它,和C语言的局部变量含义是不一样的。

局部引用在JVM中是有个数限制的,默认16个,注意管理释放。

Weak Global Reference :

弱全局引用生命周期为创建之后,直到DeleteGlobalRef。或在内存紧张时进行回收而被释放。

注意:

使用弱全局变量的时候,要时刻记着:它所指向的对象可能已经被垃圾回收了。可通过静态变量和全局变量来保持弱全局引用。

缓存方法推荐:

jobject默认是local Ref,函数环境消失时会跟随消失

在jni_onload初始化全局引用和弱全局引用

jmethodID/jfielID和jobject没有继承关系,他不是个object,只是个整数,不存在被释放与否的问题,可用全局变量保存。

jclass是由jobject继承而来的类,所以它是个jobject,需要用弱全局引用来缓存jclass对象。

局部引用管理new出来的对象,注意及时delete。

总体原则,注意释放所有对jobject的引用。

缓存与不缓存的效果对比:调用速度提高40倍

TIPS:

1. 不同线程使用JNIEnv*对象,需要AttachCurrentThread将env挂到当前线程,否则无法使用env。

2. 尽量避免频繁调用JNI或者是使用JNI传输大量到数据。

相关文章

  • Jni里的内存管理

    名词解释: JNI是什么:JNI是Java Native Interface的缩写,提供了若干API实现了Java...

  • Android开发之JNI内存模型

    Java 与JNI 内存管理是怎样的想要弄清楚Java与JNI的内存管理的关系,首先要弄清楚JVM的内存模型 其中...

  • JNI内存管理

    面试的时候遇到一些候选人的简历上写着熟悉jni,但是问的时候才发现对jni的了解仅仅是停留在java和c的方法是如...

  • AtomicInteger 源码

    基础介绍 将内存值V修改为B,否则什么都不做。 CAS操作 CAS通过调用JNI的代码实现的。JNI:Java N...

  • 使用JNI(Java Native Interface)的总结

    目录 什么是JNI?为什么使用JNI?怎么使用JNI?在IntelliJ IDEA里使用JNI 1. 什么是JNI...

  • JVM

    直接内存 使用场景:Unsafe类、NIO零拷贝、Netty的零拷贝、JNI 优点:性能更高 缺点:内存泄漏难排查...

  • iOS里的内存管理

    前言 什么是内存管理?是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且...

  • iOS里的内存管理

    前言 什么是内存管理?是指软件运行时对计算机内存资源的分配和使用的技术。其最主要的目的是如何高效,快速的分配,并且...

  • JNI内存管理之Local Reference 和 Global

    最近开发过程中遇到了JNI的Reference相关问题,了解到Local Reference和Global Ref...

  • iOS内存管理详解

    目录 block内存管理 autorelease内存管理 weak对象内存管理 NSString内存管理 new、...

网友评论

    本文标题:Jni里的内存管理

    本文链接:https://www.haomeiwen.com/subject/arcopftx.html