前言

本文隶属于专栏《100个问题搞定Java虚拟机》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见100个问题搞定Java虚拟机

正文

Java 中 native 方法的底层原理

当在 Java 代码中调用这些 native 方法时,Java 虚拟机将通过 JNI,调用至对应的 C 函数(即 native 方法对应的 C 实现)中。

Java 中的 native 方法的链接方式

一是按照 JNI 的默认规范命名所要链接的 C 函数,并依赖于 Java 虚拟机自动链接。

另一种则是在 C 代码中主动链接。

像 Java 的 C 代码

JNI 提供了一系列 API 来允许 C 代码使用 Java 语言特性。

这些 API 不仅使用了特殊的数据结构来表示 Java 类,还拥有特殊的异常处理模式。

JNI 与引用

JNI 中的引用可分为局部引用和全局引用。

这两者都可以阻止垃圾回收器回收被引用的 Java 对象。

不同的是,局部引用在 native 方法调用返回之后便会失效。

传入参数以及大部分 JNI API 函数的返回值都属于局部引用。

补充

什么情况下需要使用 JNI ?

我们经常会遇见 Java 语言较难表达,甚至是无法表达的应用场景。

比如我们希望使用汇编语言(如 X86_64 的 SIMD 指令)来提升关键代码的性能;

再比如,我们希望调用 Java 核心类库无法提供的,某个体系架构或者操作系统特有的功能。

在这种情况下,我们往往会牺牲可移植性,在 Java 代码中调用 C 代码 (C/C++) 代码,并在其中实现所需功能。

这种跨语言的调用,便需要借助 Java 虚拟机的 Java Native Interface(JNI)机制。

JNI的额外性能开销

1、进入 C 函数时,对引用类型参数的句柄化,和调整参数位置(C 调用和 Java 调用传参的方式不一样)

2、从 C 函数返回时,清理线程私有句柄块

即时编译器可能会将某些指定的本地方法调用给替换掉。这些特定的本地方法叫 intrinsics。

关于 intrinsics 可以参考我的这篇博客——HotSpot虚拟机中的intrinsic是指什么?

上一篇 下一篇