JNI引用的管理
-
在本地函数中会使用Java服务,这些服务都可以通过调用JNIEnv中封装的函数获取。我们在本地函数中可以访问所传入的引用类型参数,也可以通过JNI函数创建新的 Java 对象。这些 Java 对象显然也会受到GC的影响。所以我们需要通过JNI 的局部引用(Local Reference)和全局引用(Global Reference)来保证不让GC回收这些本地函数中可能引用到的 Java 对象。
无论是局部引用还是全局引用,其实都是通过句柄进行引用。其中,局部引用所对应的句柄有两种存储方式,一是在本地方法栈帧中,主要用于存放 C 函数所接收的来自 Java 层面的引用类型参数;另一种则是线程私有的句柄块,主要用于存放本地函数运行过程中创建的局部引用。无论是传入的引用类型参数,还是通过JNI函数返回的引用类型对象,都属于局部引用。
HotSpot VM会在启动时调用init_globals()函数初始化全局模块,init_globals()函数会间接调用到JNIHandles::initialize()函数,在这个函数中对全局的变量分配对应的JNIHandleBlock块。所以说,全局对象的句柄存储在JNIHandleBlock中。
JNIHandle分为两种,全局和局部对象引用,大部分的对象引用属于局部对象引用,最终还是调用了JNIHandleBlock来管理,因为JNIHandle没有设计一个JNIHandleMark的机制,所以在创建局部对象引用时需要明确调用JNIHandles::mark_local()函数,在回收时也需要明确调用JNIHandles::destroy_local()函数。
其实任何从C/C++调用到Java方法时都会在C/C++的栈帧中保存call wrapper,其中保存的信息非常重要,因为寄生在C/C++栈中的C/C++函数和Java方法对应的栈帧混合在一起,我们有时候要遍历C/C++栈帧,有时候需要遍历Java栈帧,当C/C++函数或Java函数执行完成后,还要能正确恢复调用者的栈帧信息并执行,这里我们不对这些内容做过多介绍,我们只关心C/C++函数使用的局部变量句柄即可。
西南地区IT社群(QQ)
- 云南
- 【昆明网页设计交流吧】243627302
- 【昆明nodejs交流吧】 243626749
- 【VUE】838405306
- 【云南程序员总群】343606807
- 【昆明UI设计】104031254
- 【云南软件外包】15547313
- 贵州
- 【PHP/java源码/站长交流群】55692114
- 四川
- 【成都Java/JavaWeb交流】86669225
- 【vaScript+PHP+MySql】116270060
- 【UI设计/设计交流学习群】135794928
- 重庆
- 【诺基亚 JAVA游戏博物馆】 559479780
- 【PHP,Java,Python,C++接单】 442103442
- 西藏