深入拆解Java虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
立即订阅
28017 人已学习
课程目录
已完结 39 讲
0/4登录后,你可以任选4讲全文学习。
开篇词 (1讲)
开篇词 | 为什么我们要学习Java虚拟机?
免费
模块一:Java虚拟机基本原理 (12讲)
01 | Java代码是怎么运行的?
02 | Java的基本类型
03 | Java虚拟机是如何加载Java类的?
04 | JVM是如何执行方法调用的?(上)
05 | JVM是如何执行方法调用的?(下)
06 | JVM是如何处理异常的?
07 | JVM是如何实现反射的?
08 | JVM是怎么实现invokedynamic的?(上)
09 | JVM是怎么实现invokedynamic的?(下)
10 | Java对象的内存布局
11 | 垃圾回收(上)
12 | 垃圾回收(下)
模块二:高效编译 (12讲)
【工具篇】 常用工具介绍
13 | Java内存模型
14 | Java虚拟机是怎么实现synchronized的?
15 | Java语法糖与Java编译器
16 | 即时编译(上)
17 | 即时编译(下)
18 | 即时编译器的中间表达形式
19 | Java字节码(基础篇)
20 | 方法内联(上)
21 | 方法内联(下)
22 | HotSpot虚拟机的intrinsic
23 | 逃逸分析
模块三:代码优化 (10讲)
24 | 字段访问相关优化
25 | 循环优化
26 | 向量化
27 | 注解处理器
28 | 基准测试框架JMH(上)
29 | 基准测试框架JMH(下)
30 | Java虚拟机的监控及诊断工具(命令行篇)
31 | Java虚拟机的监控及诊断工具(GUI篇)
32 | JNI的运行机制
33 | Java Agent与字节码注入
模块四:黑科技 (3讲)
34 | Graal:用Java编译Java
35 | Truffle:语言实现框架
36 | SubstrateVM:AOT编译框架
尾声 (1讲)
尾声 | 道阻且长,努力加餐
深入拆解Java虚拟机
登录|注册

32 | JNI的运行机制

郑雨迪 2018-10-03
我们经常会遇见 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/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《深入拆解Java虚拟机》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(9)

  • libbylg
    据说JNI的性能很差,请问这个是否是事实,如果有这个问题,那么是否有提高性能的方法
    2018-10-03
    5
  • 随心而至
    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
    1
  • Scott
    $ java -Djava.library.path=/PATH/TO/DIR/CONTAINING/libfoo.dylib org.example.Foo
    Hello, World
    这个地方应该是只写路径,不要把文件名加上

    作者回复: 多谢指出!

    2018-10-05
    1
    1
  • neohope
    老师,请问一下,使用JNI的时候,要考虑JDK版本与编译器版本的问题吗?我曾经在Windows下用JNI写过一些库,都是静态编译的,但实际测试时,发现不同版本的JDK,有时候要用不同版本的编译器。没法做到一个lib完全通用,感觉很奇怪。(不是32或64,而是vs2010,vs2015,vs2017这些。)
    2019-09-07
  • 东方
    老师: A类的方法a()调用C++ ,fork一个进程后,在子进程回调A#a()。a()打印了类的id,前后两个进程打印id是一样的。我的问题是,fork进程后,JVM还是同一个实例?

    2019-04-05
  • 未知
    在《深入理解jvm》第二版一书中,2.3.3章节讲述对象访问定位时提到,Hotspot是使用直接指针而不是句柄去访问对象的。是否是Java内部访问时使用的直接指针而native时使用的句柄??
    2018-12-28
  • 平淡
    请问这个JNIENV的参数,是当前执行native函数线程的JNIENV吗?线程的JNIENV是什么时候赋值的呢,找了好久也没找到,谢谢!
    2018-11-28
  • javaadu
    (1)JNI中也需要考虑对异常的处理
    (2)JNI中通过句柄引用java对象,
    (3)垃圾回收器会忽略jni中的局部引用和全局引用
    2018-10-23
  • Scott
    HotSpot 虚拟机是通过句柄(handle)来完成上述需求的。

    句柄是不是只是移动对象时使用,如果每次访问引用都要读内存两次,那性能影响严重

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

    2018-10-05
收起评论
9
返回
顶部