Java进阶——JNI原理简介

JNI Java Native Interface


Java源码层 —— JNI层 —— Native层

JNI(Java Native Interface)是Jave本地接口,是Java与其它语言之间相互调用的桥梁

 

主要作用

  1. 解决无法用Java语言调用Java语言不支持的依赖于操作系统平台特性的一些功能的问题;
  2. 方便整合旧的非Java语言编写的系统代码;
  3. 为了提示性能,采用其他语言(C或C++)在处理一些功能上运行效率更高。

 

Native方法注册

Navtive方法的注册将Java中的Native方法通过方法指针与JNI进行关联。

  1. 静态注册 —— 通过javac命令编译和javah命令生成JNI方法的.h文件,方法首次调用时进行关联,即保存JNI的函数指针
  2. 动态注册 —— 用JNINativeMethod数据结构记录Java中的Native方法和JNI方法的关联,在调用System.loadLibrary()方法后,会查找加载的so库中的JNI_OnLoad方法,如果存在则调用该方法,其最终调用JNIEnv的RegisterNatives方法来完成动态注册。

 

数据类型转换

Java的数据类型到了JNI层就需要转换为JNI层的数据类型。基本数据类型的转换处理void类型,其他只需在Java的类型前添加“j”即可。引用数据类型同样需在Java的类型前添加“j”即可,数组类型以“Array”结尾,除Class、String和Throwable外的其他所有类型都用“jobject”表示。引用数据类型拥有有继承关系。  

基本数据类型的转换和签名
JavaNative签名
bytejbyteB
charjcharC
shortjshortS
intjintI
floatjfloatF
doublejdoubleD
longjlongJ
booleanjbooleanZ
voidvoidV

 

 

基本数据类型的转换和签名
JavaNative签名
所有对象jobjectL+classname+;
ClassjclassLjava/lang/Class;
StringjstringLjava/lang/String;
ThrowablejthrowableLjava/lang/Throwable;
Object[]jobjectArray[L+classname+;
byte[]jbyteArray[B
char[]jcharArray[C
short[]jshortArray[S
int[]jintArray[I
float[]jfloatArray[F
double[]jdoubleArray[D
long[]jlongArray[J
boolean[]jbooleanArray[Z

方法签名

因为Java语法支持方法重载,单单通过方法名通常无法准确找到对应方法,所有引入了方法签名概念,作用是通过方法签名可以准确定位方法。

方法签名的格式是:(参数类型签名格式…)返回类型签名格式

 

JNIEnv

JNIEnv代表了在Native中的Java环境。JNIEnv在jni.h文件中被定义,在C中JNIEnv类型是JNINativeInterface结构,在JNINativeInterface结构中定义了一系列和JNIEnv对应的函数指针,通过这些函数指针的定义,就能查找到Java虚拟机中的JNI函数表,而从实现JNI层在Java虚拟机中方法的调用。在调用Java类的成员变量和方法是通过初始化方法中获取jfieldID和jmethodID来获取变量引用和调用对应方法,可以调用GetObjectField方法传入jfieldID获取对应Java类的成员变量,调用CallVoidMethod或CallStaticVoidMethod方法传入jclass和jmethodID调用在Java对应类的类的方法或类方法(静态方法)。注意的是在不同线程中的JNIEnv并不是同一个,因此它不能跨线程,是线程独立的。

 

JNI中的引用类型

  1. 本地引用——类似Java方法中的局部变量的引用,当Native方法返回时,本地引用会被自动释放,只能在创建它的线程中有效不能跨线程使用,受JVM管理。JNIEnv基本上大部分方法调用返回的引用都是本地引用。
  2. 全局引用——类型Java类中的成员变量,当Native方法返回时,全局引用不会被自动释放,也不会被GC回收,所以需要手动进行释放,可以跨线程使用,不受JVM管理。全局引用在JNIEnv中调用NewGlobalRef方法来创建,调用DeleteGlobalRef方法来释放。
  3. 弱全局引用——是一种特殊的全局引用,可以被GC回收,因此在使用该引用前需要调用JNIEnv的IsSameObject方法来进行非空判断。弱全局引用在JNIEnv中调用NewWeakGlobalRef方法来创建,调用DeleteWeakGlobalRef方法来释放。

 

Java虚拟机中的本地方法栈

本地方法栈在Java运行时内存模型中与Java虚拟机栈及其相似,不同点是Java虚拟机栈中操作的是Java方法,而本地方法栈操作Native方法。虚拟机规范中对本地方法栈中的方法使用的语言、使用方式与数据结构并没有强制规定,因此具体的虚拟机可以自由实现它。有些虚拟机将Java虚拟机栈和本地方法栈合二为一。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值