32 | JNI的运行机制
郑雨迪
该思维导图由 AI 生成,仅供参考
我们经常会遇见 Java 语言较难表达,甚至是无法表达的应用场景。比如我们希望使用汇编语言(如 X86_64 的 SIMD 指令)来提升关键代码的性能;再比如,我们希望调用 Java 核心类库无法提供的,某个体系架构或者操作系统特有的功能。
在这种情况下,我们往往会牺牲可移植性,在 Java 代码中调用 C/C++ 代码(下面简述为 C 代码),并在其中实现所需功能。这种跨语言的调用,便需要借助 Java 虚拟机的 Java Native Interface(JNI)机制。
关于 JNI 的例子,你应该特别熟悉 Java 中标记为native的、没有方法体的方法(下面统称为 native 方法)。当在 Java 代码中调用这些 native 方法时,Java 虚拟机将通过 JNI,调用至对应的 C 函数(下面将 native 方法对应的 C 实现统称为 C 函数)中。
举个例子,Object.hashCode方法便是一个 native 方法。它对应的 C 函数将计算对象的哈希值,并缓存在对象头、栈上锁记录(轻型锁)或对象监视锁(重型锁所使用的 monitor)中,以确保该值在对象的生命周期之内不会变更。
native 方法的链接
在调用 native 方法前,Java 虚拟机需要将该 native 方法链接至对应的 C 函数上。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
JNI是Java Native Interface的缩写,是Java虚拟机提供的一种机制,用于在Java代码中调用C/C++代码,实现跨语言调用。本文详细介绍了JNI的运行机制,包括native方法的链接方式和实现过程。文章首先介绍了native方法的概念,以及在Java代码中如何声明和调用native方法。然后详细讲解了两种native方法的链接方式,以及如何在C代码中主动链接。文章还给出了一个具体的示例,展示了如何实现一个native方法,并通过gcc命令将其编译成动态链接库,然后在Java程序中加载并调用该动态链接库。此外,文章还介绍了JNI的API,包括JNI函数的特性和异常处理模式。另外,文章还介绍了JNI中的引用类型,包括局部引用和全局引用的概念,以及它们在垃圾回收中的作用。总的来说,本文通过具体的例子和代码,详细介绍了JNI的运行机制和实现过程,对于想要了解JNI的读者来说,是一份很有价值的参考资料。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
《深入拆解 Java 虚拟机》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(14)
- 最新
- 精选
- Scott$ java -Djava.library.path=/PATH/TO/DIR/CONTAINING/libfoo.dylib org.example.Foo Hello, World 这个地方应该是只写路径,不要把文件名加上
作者回复: 多谢指出!
2018-10-0536 - ScottHotSpot 虚拟机是通过句柄(handle)来完成上述需求的。 句柄是不是只是移动对象时使用,如果每次访问引用都要读内存两次,那性能影响严重
作者回复: JNI里每次访问都要通过句柄,理论上你可以解引用拿到oop,但是不安全,一旦垃圾回收在你用oop时移动了对象,你就会操作一个实际上已经失效了的oop
2018-10-053 - LJNI 的运行机制: 1. Java 中的 native 方法的链接方式主要有两种: 1、自动链接 按照 JNI 的默认规范命名所要链接的 C 函数,并依赖于 Java 虚拟机自动链接。 2、主动链接 另一种则是在 C 代码中主动链接。 2. JNI 提供了一系列 API 来允许 C 代码使用 Java 语言特性。 1、映射了 Java ⇋ C 的 基本数据类型 和 引用数据类型 int -> jint ... 2、异常处理 3. 防止 C代码 中 引用到的 Java对象被 JVM GC 在C代码中,可以访问传入的引用类型参数,也可以 通过 JNI API 创建新的 Java 对象。 Java 虚拟机需要一种机制,来告知垃圾回收算法,不要回收这些 C 代码中可能引用到的 Java 对象。 -- JNI 的 局部引用(Local Reference)和 全局引用(Global Reference) 这两者都可以 阻止垃圾回收器 回收 被引用的 Java对象。 不同的是,局部引用 在 native 方法调用返回之后便会失效。传入参数 以及大部分 JNI API 函数的返回值 都属于 局部引用。 4. JNI 的额外性能开销 1、进入 C 函数时,对引用类型参数的句柄化,和调整参数位置(C 调用和 Java 调用传参的方式不一样) 2、从 C 函数返回时,清理线程私有句柄块2020-07-2912
- libbylg据说JNI的性能很差,请问这个是否是事实,如果有这个问题,那么是否有提高性能的方法2018-10-037
- 随心而至linux下生成文中对应libfoo.so命令如下: gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -o libfoo.so -shared foo.c 另外:System.load和System.loadLibrary 可以互换。 动手做一下,就明白了。2019-10-314
- 德惠先生老师好像没有提到GC_LOCKER机制,并不是所有引用都会被gc直接略过2020-03-032
- 小陈不错,之前不懂的懂了2020-03-291
- 饭粒Linux: # javac -h . org/example/Foo.java # # gcc -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -fPIC -o libfoo.so -shared foo.c # # tree ./ ./ ├── foo.c ├── libfoo.so ├── org │ └── example │ ├── Foo.class │ └── Foo.java └── org_example_Foo.h 2 directories, 5 files # java -Djava.library.path=. org.example.Foo Hello, World2019-12-281
- 未知在《深入理解jvm》第二版一书中,2.3.3章节讲述对象访问定位时提到,Hotspot是使用直接指针而不是句柄去访问对象的。是否是Java内部访问时使用的直接指针而native时使用的句柄??2018-12-281
- javaadu(1)JNI中也需要考虑对异常的处理 (2)JNI中通过句柄引用java对象, (3)垃圾回收器会忽略jni中的局部引用和全局引用2018-10-231
收起评论