深入拆解 Java 虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
87446 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
模块四:黑科技 (3讲)
深入拆解 Java 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

32 | JNI的运行机制

C代码中主动链接
Java虚拟机自动链接
性能和正确性陷阱
引用类型
JNI的API
JNI的链接方式
句柄
JNI函数
垃圾回收机制
引用类型的数据结构
基本类型的对应关系
JNIEnv
链接方式
native方法
Java Native Interface(JNI)
总结与实践
局部引用与全局引用
JNI的API
native方法的链接
介绍
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 函数)中。
public class Object {
public native int hashCode();
}
举个例子,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
立即购买
登录 后留言

全部留言(14)

  • 最新
  • 精选
  • Scott
    $ java -Djava.library.path=/PATH/TO/DIR/CONTAINING/libfoo.dylib org.example.Foo Hello, World 这个地方应该是只写路径,不要把文件名加上

    作者回复: 多谢指出!

    2018-10-05
    3
    6
  • Scott
    HotSpot 虚拟机是通过句柄(handle)来完成上述需求的。 句柄是不是只是移动对象时使用,如果每次访问引用都要读内存两次,那性能影响严重

    作者回复: JNI里每次访问都要通过句柄,理论上你可以解引用拿到oop,但是不安全,一旦垃圾回收在你用oop时移动了对象,你就会操作一个实际上已经失效了的oop

    2018-10-05
    3
  • L
    JNI 的运行机制: 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-29
    12
  • libbylg
    据说JNI的性能很差,请问这个是否是事实,如果有这个问题,那么是否有提高性能的方法
    2018-10-03
    7
  • 随心而至
    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-31
    4
  • 德惠先生
    老师好像没有提到GC_LOCKER机制,并不是所有引用都会被gc直接略过
    2020-03-03
    2
  • 小陈
    不错,之前不懂的懂了
    2020-03-29
    1
  • 饭粒
    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, World
    2019-12-28
    1
  • 未知
    在《深入理解jvm》第二版一书中,2.3.3章节讲述对象访问定位时提到,Hotspot是使用直接指针而不是句柄去访问对象的。是否是Java内部访问时使用的直接指针而native时使用的句柄??
    2018-12-28
    1
  • javaadu
    (1)JNI中也需要考虑对异常的处理 (2)JNI中通过句柄引用java对象, (3)垃圾回收器会忽略jni中的局部引用和全局引用
    2018-10-23
    1
收起评论
显示
设置
留言
14
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部