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

22 | HotSpot虚拟机的intrinsic

popcnt指令
PCMPESTRI指令
Integer.bitCount intrinsic的性能提升
基本类型的包装类、Object类、Math类、System类中各个功能性方法
String类、StringLatin1类、StringUTF16类和Arrays类的方法
StringBuilder和StringBuffer类的方法
Unsafe类的方法
方法内联过程
即时编译器
X86_64体系架构
三百多个intrinsic
特殊的IR节点
桩程序
总结与实践
已有intrinsic简介
intrinsic与方法内联的过程
intrinsic与CPU指令的例子
Compact Strings概念
Java 9之前的字符串存储方式
总结与实践
已有intrinsic简介
intrinsic与方法内联
intrinsic与CPU指令
intrinsic数量
intrinsic实现方式
@HotSpotIntrinsicCandidate注解
参考文章
HotSpot虚拟机
intrinsic
HotSpot虚拟机的intrinsic

该思维导图由 AI 生成,仅供参考

前不久,有同学问我,String.indexOf方法和自己实现的indexOf方法在字节码层面上差不多,为什么执行效率却有天壤之别呢?今天我们就来看一看。
public int indexOf(String str) {
if (coder() == str.coder()) {
return isLatin1() ? StringLatin1.indexOf(value, str.value)
: StringUTF16.indexOf(value, str.value);
}
if (coder() == LATIN1) { // str.coder == UTF16
return -1;
}
return StringUTF16.indexOfLatin1(value, str.value);
}
为了解答这个问题,我们来读一下String.indexOf方法的源代码(上面的代码截取自 Java 10.0.2)。
在 Java 9 之前,字符串是用 char 数组来存储的,主要为了支持非英文字符。然而,大多数 Java 程序中的字符串都是由 Latin1 字符组成的。也就是说每个字符仅需占据一个字节,而使用 char 数组的存储方式将极大地浪费内存空间。
Java 9 引入了 Compact Strings[1]的概念,当字符串仅包含 Latin1 字符时,使用一个字节代表一个字符的编码格式,使得内存使用效率大大提高。
假设我们调用String.indexOf方法的调用者以及参数均为只包含 Latin1 字符的字符串,那么该方法的关键在于对StringLatin1.indexOf方法的调用。
下面我列举了StringLatin1.indexOf方法的源代码。你会发现,它并没有使用特别高明的算法,唯一值得注意的便是方法声明前的@HotSpotIntrinsicCandidate注解。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

HotSpot虚拟机中的intrinsic是指被标注了`@HotSpotIntrinsicCandidate`注解的方法,在编译过程中会被替换成高效的指令序列。这种优化方式依赖于具体的CPU指令,因此在不同体系架构上的实现方式也不同。文章通过具体的例子,如`StringLatin1.indexOf`、`Math.addExact`和`Integer.bitCount`方法,解释了intrinsic与CPU指令的关系。另外,文章还介绍了intrinsic与方法内联的实现方式,即时编译器会将对原方法的调用替换成特殊的IR节点,并最终生成指定的CPU指令。通过这种优化方式,即时编译器能够将一些native方法内联进来,并消除JNI的性能开销,使得程序执行效率大大提高。HotSpot虚拟机中的intrinsic数量随着不同版本的Java而变化,且其他虚拟机未必维护了这些intrinsic的高效实现。因此,开发者需要在编写代码时考虑不同虚拟机的特性,以获得更好的性能表现。 HotSpot虚拟机定义了三百多个intrinsic,其中包括`Unsafe`类的方法、`StringBuilder`和`StringBuffer`类的方法、`String`类、`StringLatin1`类、`StringUTF16`类和`Arrays`类的方法,以及基本类型的包装类、`Object`类、`Math`类、`System`类中各个功能性方法、反射API、`MethodHandle`类中与调用机制相关的方法、压缩、加密相关方法等。这些intrinsic的实现方式包括桩程序和特殊的IR节点,能够带来性能提升。读者可以通过实践体验`Integer.bitCount` intrinsic带来的性能提升。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(24)

  • 最新
  • 精选
  • ^_^
    我个人觉得老师讲的非常好,这些东西更像是讲解一个系统似的,让我们更懂他们的运行机制,推算出我们系统每个类、方法和属性在jvm上的运作模式。这课程真的对于我们java开发的真的是太有帮助了,不想某某些课程占着实践经验的名义混。感谢老师辛苦啦!

    作者回复: 多谢支持!

    2018-09-10
    18
  • 随心而至
    赞,之前学习了深入理解计算机原理这门课,再联系这一节就知道intrinsic想做什么了。 JVM 自身不是跨平台的,Windows,Linux都有各自的安装包,也就是JVM帮我们做了不同操作系统及底层体系结构的兼容;但是针对每一个具体的CPU,其自身提供的指令,寄存器,以及SIMD等优化机制并没有得到利用,而intrinsic的产生正是为了利用这些。 个人理解,有不对之处,请老师和各位同学指出。

    作者回复: 对的,许多intrinsics 都会依赖特殊的CPU指令来优化执行效率的。 说个趣闻,Intel曾经向OpenJDK提交了一大堆浮点数算法作为java.lang.Math中部分方法的intrinsic,比如sin cos这些,除了他们没人看的懂。结果在某些情况下算出来的结果是错的。。后来他们又提交了一堆更正过的天书代码,希望是对的吧,哈哈

    2019-10-25
    2
    15
  • Geek_09d838
    我觉得有些功能你要先知道,再去考虑能否会用到这些功能。

    作者回复: 嗯嗯! 我的想法是,在这个专栏中介绍JVM各个组件的设计与实现。之后当开发人员在遇到性能问题时,能够联想到具体是哪个组件可能出了问题,从而针对性地去做调优。

    2018-09-10
    6
  • Scott
    我还是看得蛮过瘾的,周一三五早上起来第一件事就是看更新,的确可能不是很实用,但是对于对虚拟机感兴趣的同学来讲,是满足了好奇心

    作者回复: 谢谢支持!

    2018-09-10
    5
  • 白三岁
    我看了下java8中没有找到这个注解。调用从源码复制出来的方法和直接调用源码的方法没有性能上的差别。是java8没有加入这种优化吗

    作者回复: Java8已经有一些intrinsic,但不多。 这个注解应该是Java 9引入的,它的意思其实是用来提醒JDK开发人员注意虚拟机里有对应的intrinsic,改动的话需要通知我们

    2018-09-27
    3
  • Len
    我觉得老师讲的非常好,尤其是上两讲讲方法内联,结合老师讲的,在课后我又恶补了一下 IR 方面的知识,收获很大。 尽管目前我的工作不会直接用到这方面的知识,但我相信这些底层机制、原理性的知识点,对成长为一名优秀的工程师是必备的。

    作者回复: 多谢支持!

    2018-09-10
    3
  • ahern88
    我觉得这份虚拟机教程写的知识有点偏,不够实用,大家觉得呢

    作者回复: 多谢建议! JVM对用户来说是透明的,可调优的参数也在逐渐减少,总体朝着自适配前进。所以把本专栏当成工具书来看的话,确实没有多少实用性。 不过就算是自适配的虚拟机,也有覆盖不到的场景。专栏前面这两部分,正是在介绍JVM各个模块的设计与实现,以便开发人员在发现性能问题时能够联想到可能出问题的具体模块。 接下来的第三部分会介绍一些性能监控分析工具,希望会对你有所帮助。

    2018-09-10
    3
    3
  • 饭粒
    文中说 @HotSpotIntrinsicCandidate 如果不是 HotSpot 的虚拟机就退化使用 JDK 源码的方式。但如果某个 @HotSpotIntrinsicCandidate 注解的方法 X86_64 有指令可以优化,但其他架构体系比如 AMD64 没有相应的指令或者指令不同这个过程是怎样的?

    作者回复: 其他架构没有的话就沿用Java实现。另x86_64和amd64是同一个架构

    2019-12-24
    2
    2
  • JZ
    Java8中并没有看到相应的注解,如String类的indexOf方法,Java8中没有类似的优化?

    作者回复: 记得是9之后才大量加入的

    2018-09-23
  • bradsun
    这个为什么不都是独立的形式。而且只有少部分是独立的。谢谢

    作者回复: 不好意思没明白你的问题。什么是独立的?

    2018-09-11
收起评论
显示
设置
留言
24
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部