java 的 JNI介绍
内容源于JDK API文档JNI
脑图会列出JNI的功能框架。
JNI技术不做深入,本篇文档描述JNI的使用场景、整体设计、和一个简单用例。方便记忆和理解JNI。
一、概述
提供调用第三方类库,和本地方式的方式。使用场景
- java的类库不支持运行平台的特性
- 调用其他语言的库比如C
- 要求函数的执行效率要高,封装成本地方法,被java调用
JNI的功能
- 创建、查看、升级 java对象
- 调用java方法
- 捕获异常
- 加载类和获取类的信息
- 演示运行时类型检查
二、整体设计
想要调用一个本地方法,通过JNI接口执行
,获取一个属于当前线程的JNI指针
,这个指针就包含注册好的本地方法
。
-
- 可以类比为JNI interface pointer为类的定义
-
- Pointer指针为实例,每个线程独有,线程之前不能传递。vm的实现者可以在Pointer指针实例的区域开辟一个控件来保存变量信息等,这个就是我们常理解的
虚机方法栈
,线程级别的。
- Pointer指针为实例,每个线程独有,线程之前不能传递。vm的实现者可以在Pointer指针实例的区域开辟一个控件来保存变量信息等,这个就是我们常理解的
-
- 具体的蹦迪方法数组就想方法的定义。这样做的好处是,vm不绑定具体的方式,而是只维护一个数组。并且vm可以有多个这样的数组:比如开发阶段用一个,但是check多,耗时多;运行期间用另外一个,check少效率高。
三、编译、加载和链接
System.loadLibrary()
用来加载第三方类库。
- 定义了一个类
Pkg.Clg
,该类加载pkg_Cls
库。比如linux系统就是pkg_Cls.so,win32就是pkg_Cls.dll。 - 定义了方法
native double f(int i, String s)
。自动去根据签名在本地方法库中寻找。 - 注意开发者可以用一个库来存储本地方法,只要被同一个类加载器加载。供应商提供这样的库是应该谨慎选择名称,避免库名冲突。
- 被加载的方法分为静态方法和非静态方法。使用
库名+方法名
来标识静态方法,方法名
是非静态。
库名 | 方法名 | 类别 | 形式 |
---|---|---|---|
L | JNI_OnLoad | 静态 | JNI_OnLoad_L |
L | JNI_OnLoad | 非静态 | JNI_OnLoad |
注意JNI_OnLoad_L和JNI_OnLoad同时存在时会被忽略。
- 开发者也可以用
RegisterNatives()
去和一个类链接,这个方法对静态方法十分有用
四、本地方法名称的解析规则
先看这样一个类
- 有两个同名的方法,但不用担心方法冲突。第一个方法在依赖中找,第二个方法去natvie方法中
- native int g(double d);如何对应到本地方法呢,有转化规则。
中的方法对应到C文件中方式是
- java前缀
- 类名
- 方法名
- 参数类型
- 参数数量
五、引用java对象
在Java和本机代码之间复制原始类型,例如整数,字符等。另一方面,任意的Java对象都是通过引用传递的。VM必须跟踪已传递给本机代码的所有对象,以便垃圾回收器不会释放这些对象。反过来,本机代码必须具有一种通知VM不再需要对象的方法。另外,垃圾收集器必须能够移动由本机代码引用的对象。
- 数组
- 方法
- 字段field
六、异常的处理机制
- 类型检查(JNI不检查类型)
- 异常处理机制。