文章目录

  • 简介
  • String压缩
  • 分层编译(Tiered Compilation)
  • Code Cache分层
  • 新的JIT编译器Graal
  • 前置编译
  • 压缩对象指针
  • Zero-Based 压缩指针
  • Escape analysis逃逸分析

简介

上一篇文章我们讲到了JVM为了提升解释的性能,引入了JIT编译器,今天我们再来从整体的角度,带小师妹看看JDK14中的JVM有哪些优化的方面,并且能够从中间得到那些启发。

更多精彩内容且看:

  • 区块链从入门到放弃系列教程-涵盖密码学,超级账本,以太坊,Libra,比特币等持续更新
  • Spring Boot 2.X系列教程:七天从无到有掌握Spring Boot-持续更新
  • Spring 5.X系列教程:满足你对Spring5的一切想象-持续更新
  • java程序员从小工到专家成神之路(2020版)-持续更新中,附详细文章教程

String压缩

小师妹:F师兄,上次你给我讲的JIT真的是受益匪浅,原来JVM中还有这么多不为人知的小故事。不知道除了JIT之外,JVM还有没有其他的性能提升的姿势呢?

姿势当然有很多种,先讲一下之前提到过的,在JDK9中引入的字符串压缩。

在JDK9之前,String的底层存储结构是char[],一个char需要占用两个字节的存储单位。

因为大部分的String都是以Latin-1字符编码来表示的,只需要一个字节存储就够了,两个字节完全是浪费。

于是在JDK9之后,字符串的底层存储变成了byte[]。

目前String支持两种编码格式LATIN1和UTF16。

LATIN1需要用一个字节来存储。而UTF16需要使用2个字节或者4个字节来存储。

在JDK9中,字符串压缩是默认开启的。你可以使用

 -XX:-CompactStrings

来控制它。

分层编译(Tiered Compilation)

为了提升JIT的编译效率,并且满足不同层次的编译需求,引入了分层编译的概念。

大概来说分层编译可以分为三层:

  1. 第一层就是禁用C1和C2编译器,这个时候没有JIT进行。
  2. 第二层就是只开启C1编译器,因为C1编译器只会进行一些简单的JIT优化,所以这个可以应对常规情况。
  3. 第三层就是同时开启C1和C2编译器。

在JDK7中,你可以使用下面的命令来开启分层编译:

-XX:+TieredCompilation

而在JDK8之后,恭喜你,分层编译已经是默认的选项了,不用再手动开启。

Code Cache分层

Code Cache就是用来存储编译过的机器码的内存空间。也就说JIT编译产生的机器码,都是存放在Code Cache中的。

Code Cache是以单个heap形式组织起来的连续的内存空间。

如果只是用一个code heap,或多或少的就会引起性能问题。为了提升code cache的利用效率,JVM引入了Code Cache分层技术。

分层技术是什么意思呢?

就是把不同类型的机器码分门别类的放好,优点嘛就是方便JVM扫描查找,减少了缓存的碎片,从而提升了效率。

下面是Code Cache的三种分层:

新的JIT编译器Graal

之前的文章我们介绍JIT编译器,讲的是JIT编译器是用C/C++来编写的。

而新版的Graal JIT编译器则是用java来编写的。对的,你没看错,使用java编写的JIT编译器。

有没有一种鸡生蛋,蛋生鸡的感觉?不过,这都不重要,重要的是Graal真的可以提升JIT的编译性能。

Graal是和JDK一起发行的,作为一个内部的模块:jdk.internal.vm.compiler。

Graal和JVM是通过JVMCI(JVM Compiler Interface)来进行通信的。其中JVMCI也是一个内部的模块:jdk.internal.vm.ci。

注意,Graal只在Linux-64版的JVM中支持,你需要使用 -XX:+UnlockExperimentalVMOptions -XX:+UseJVMCICompiler 来开启Graal特性。

前置编译

我们知道在JIT中,通常为了找到热点代码,JVM是需要等待代码执行一定的时间之后,才开始进行本地代码的编译。这样做的缺点就是需要比较长的时间。

同样的,如果是重复的代码,没有被编译成为机器码,那么对性能就会有影响。

而AOT(Ahead-of-time)就厉害了,看名字就知道是提前编译的意思,根本就不需要等待,而是在JVM启动之前就开始编译了。

AOT提供了一个java tool,名字叫做jaotc。显示jaotc的命令格式:

jaotc <options> <list of classes or jar files>
jaotc <options> <--module name>

比如,我们可以这样提前编译AOT库,以供在后面的JVM中使用:

jaotc --output libHelloWorld.so HelloWorld.class
jaotc --output libjava.base.so --module java.base

上面代码提前编译了HelloWorld和它的依赖module java.base。

然后我们可以在启动HelloWorld的时候,指定对应的lib:

java -XX:AOTLibrary=./libHelloWorld.so,./libjava.base.so HelloWorld

这样在JVM启动的时候,就回去找相应的AOTLibrary。

注意,AOT是一个 Linux-x64上面的体验功能。

压缩对象指针

对象指针用来指向一个对象,表示对该对象的引用。通常来说在64位机子上面,一个指针占用64位,也就是8个字节。而在32位机子上面,一个指针占用32位,也就是4个字节。

实时上,在应用程序中,这种对象的指针是非常非常多的,从而导致如果同样一个程序,在32位机子上面运行和在64位机子上面运行占用的内存是完全不同的。64位机子内存使用可能是32位机子的1.5倍。

而压缩对象指针,就是指把64位的指针压缩到32位。

怎么压缩呢?64位机子的对象地址仍然是64位的。压缩过的32位存的只是相对于heap base address的位移。

我们使用64位的heap base地址+ 32位的地址位移量,就得到了实际的64位heap地址。

对象指针压缩在Java SE 6u23 默认开启。在此之前,可以使用-XX:+UseCompressedOops来开启。

Zero-Based 压缩指针

刚刚讲到了压缩过的32位地址是基于64位的heap base地址的。而在Zero-Based 压缩指针中,64位的heap base地址是重新分配的虚拟地址0。这样就可以不用存储64位的heap base地址了。

Escape analysis逃逸分析

最后,要讲的是逃逸分析。什么叫逃逸分析呢?简单点讲就是分析这个线程中的对象,有没有可能会被其他对象或者线程所访问,如果有的话,那么这个对象应该在Heap中分配,这样才能让对其他的对象可见。

如果没有其他的对象访问,那么完全可以在stack中分配这个对象,栈上分配肯定比堆上分配要快,因为不用考虑同步的问题。

我们举个例子:

  public static void main(String[] args) {example();}public static void example() {Foo foo = new Foo(); //allocBar bar = new Bar(); //allocbar.setFoo(foo);}
}class Foo {}class Bar {private Foo foo;public void setFoo(Foo foo) {this.foo = foo;}
}

上面的例子中,setFoo引用了foo对象,如果bar对象是在heap中分配的话,那么引用的foo对象就逃逸了,也需要被分配在heap空间中。

但是因为bar和foo对象都只是在example方法中调用的,所以,JVM可以分析出来没有其他的对象需要引用他们,那么直接在example的方法栈中分配这两个对象即可。

逃逸分析还有一个作用就是lock coarsening。

为了在多线程环境中保证资源的有序访问,JVM引入了锁的概念,虽然锁可以保证多线程的有序执行,但是如果实在单线程环境中呢?是不是还需要一直使用锁呢?

比如下面的例子:

public String getNames() {Vector<String> v = new Vector<>();v.add("Me");v.add("You");v.add("Her");return v.toString();
}

Vector是一个同步对象,如果是在单线程环境中,这个同步锁是没有意义的,因此在JDK6之后,锁只在被需要的时候才会使用。

这样就能提升程序的执行效率。

本文作者:flydean程序那些事

本文链接:http://www.flydean.com/jvm-performance-enhancements/

本文来源:flydean的博客

欢迎关注我的公众号:程序那些事,更多精彩等着您!

小师妹学JVM之:JDK14中JVM的性能优化相关推荐

  1. 小师妹学JavaIO之:NIO中那些奇怪的Buffer

    文章目录 简介 Buffer的分类 Big Endian 和 Little Endian aligned内存对齐 总结 简介 妖魔鬼怪快快显形,今天F师兄帮助小师妹来斩妖除魔啦,什么BufferB,B ...

  2. 小师妹学JavaIO之:NIO中Channel的妙用

    文章目录 简介 Channel的分类 FileChannel Selector和Channel DatagramChannel SocketChannel ServerSocketChannel As ...

  3. 小师妹学JVM之:逃逸分析和TLAB

    文章目录 简介 逃逸分析和栈上分配 TLAB简介 TLAB详解 设置TLAB空间的大小 TLAB中大对象的分配 TLAB空间中的浪费 总结 简介 逃逸分析我们在JDK14中JVM的性能优化一文中已经讲 ...

  4. 小师妹学JVM之:JVM的架构和执行过程

    文章目录 简介 JVM是一种标准 java程序的执行顺序 JVM的架构 类加载系统 运行时数据区域 执行引擎 总结 简介 JVM也叫Java Virtual Machine,它是java程序运行的基础 ...

  5. 小师妹学IO系列文章集合-附PDF下载

    文章目录 第一章 IO的本质 IO的本质 DMA和虚拟地址空间 IO的分类 IO和NIO的区别 总结 第二章 try with和它的底层原理 简介 IO关闭的问题 使用try with resourc ...

  6. 小师妹学JavaIO之:文件读取那些事

    文章目录 简介 字符和字节 按字符读取的方式 按字节读取的方式 寻找出错的行数 总结 简介 小师妹最新对java IO中的reader和stream产生了一点点困惑,不知道到底该用哪一个才对,怎么读取 ...

  7. 小师妹学JavaIO之:文件系统和WatchService

    文章目录 简介 监控的痛点 WatchService和文件系统 WatchSerice的使用和实现本质 总结 简介 小师妹这次遇到了监控文件变化的问题,F师兄给小师妹介绍了JDK7 nio中引入的Wa ...

  8. Java虚拟机这一块 —— JVM 调优和深入了解性能优化

    JVM 调优和深入了解性能优化 JVM 调优的本质 GC 调优原则 调优的原则 目的 GC 调优 调优步骤 日志分析 阅读 GC 日志 -XX:+UseSerialGC -XX:+UseParNewG ...

  9. Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析

    Java生鲜电商平台-SpringCloud微服务架构中网络请求性能优化与源码解析 说明:Java生鲜电商平台中,由于服务进行了拆分,很多的业务服务导致了请求的网络延迟与性能消耗,对应的这些问题,我们 ...

最新文章

  1. alt+shift+j,添加日期、作者等
  2. Endian Bitfiled
  3. Java:多态的概念和案例实现
  4. Openssl 之大数运算函数 BN
  5. 微信小程序把玩(三十三)Record API
  6. java读写html文件时出现中文乱码问题的解决方法
  7. php ftp a站到b站,phpcmsv9在做推送中将a站文章内容完美的推送b站点下
  8. 3月4日见!Redmi Note 10系列屏幕升级:首次采用Super AMOLED屏
  9. 【操作系统】第1章 操作系统概论
  10. Linux在终端搜索的两条命令
  11. 转载:LOG_ARCHIVE_DEST_n参数属性——DATA GUARD概念和管理
  12. var模型的建模步骤python_Python语言之概述建模步骤
  13. Filter 实现图片转发
  14. 2018年新媒体趋势解读:大航海时代结束,圈地运营开始
  15. ol-地图上添加图标
  16. 20230106 作业
  17. abp.ajax get,ABP入门系列之Json格式化
  18. WIFI基础入门--802.11k--无线局域网络频谱测量
  19. 华为前员工因离职补偿被拘251天!热搜被撤欲掩盖真相?听听当事人的讲述......
  20. 澤地萃 (易經大意 韓長庚)

热门文章

  1. EOJ_1024_表达式
  2. 基于java的餐饮管理系统_基于java的餐饮管理系统
  3. ATC计算机会议,三项成果被计算机系统重要国际会议USENIX ATC和HotStorage收录
  4. codeforces contest 1119
  5. 25.智能指针.rs
  6. boost中unordered_map的用法
  7. 字符串匹配--Sunday算法
  8. 深入理解Java内存架构
  9. 面试官:限制系统扩展能力的瓶颈有哪些?
  10. 杜比收购低延迟流媒体平台Millicast