JDK17 与 JDK11 特性差异浅谈( 二 )


JDK17 与 JDK11 特性差异浅谈

文章插图
图片
  • 吞吐量 (thrpt) :单位时间内完成的操作次数,也可以理解为每秒能处理的事务数 。
  • 平均时间 (avgt) :每次操作所需的平均时间 。
  • 样本时间 (sample) :随机取样,最后输出取样结果的分布,例如“99%的调用在xxx毫秒以内 , 99.99%的调用在xxx毫秒以内” 。
  • 单次启动时间 (ss) :SingleShotTime ,度量一次操作的运行时间,即每次迭代前都会重新初始化状态 。
@State类注解,JMH 测试类必须使用 @State 注解,State 定义了一个类实例的生命周期,可以类比 SpringBean 的 Scope。由于 JMH 允许多线程同时执行测试,不同的选项含义如下:
Scope.Thread :默认的 State ,每个测试线程分配一个实例 。
Scope.Benchmark :所有测试线程共享一个实例 , 用于测试有状态实例在多线程共享下的性能 。
Scope.Group :每个线程组共享一个实例 。
如果你想测试一个对象在多线程环境下的行为,你可以选择 Scope.Benchmark。如果你想要每个线程都有自己的状态,你可以选择 Scope.Thread。如果你想要在同一线程组内的所有线程共享状态,你可以选择 Scope.Group。
@OutputTimeUnitbenchmark 结果所使用的时间单位,可用于类或者方法注解 , 使用 java.util.concurrent.TimeUnit 中的标准时间单位 。
@Benchmark方法注解,表示该方法是需要进行 benchmark 的对象 。
1.3 生成类数据共享特性优化背景:在同一个物理机上启动多个 JVM 时,如果每个虚拟机都单独装载自己需要的所有类,启动成本和内存占用是比较高的 。所以引入了类数据共享机制 ( Class Data Sharing  , 简称 CDS ) 的概念,通过把一些核心类在每个 JVM 间共享,每个 JVM 只需要装载自己的应用类即可 。
JDK12 之前想要利用 CDS 的用户,必须 -Xshare:dump 作为额外的步骤来运行 。
JDK12 针对 64 位平台使其默认生成类数据共享 ( CDS ) 归档 。
好处:JVM启动时间减少了 。因为核心类是共享的 , 所以 JVM 的内存占用也减少了 。
JDK13 则支持在应用运行之后进行动态归档 。需要使用 -XX:ArchiveClassesAtExit=filename.jsa 选项来指定一个文件,JVM 会在退出时将应用程序类和标准库类的元数据写入这个文件 。然后,在下一次启动 JVM 时,你可以使用 -XX:SharedArchiveFile=filename.jsa 选项来指定刚才创建的文件 。
好处:这个特性允许 JVM 在运行时捕获类的元数据 , 然后在下一次 JVM 启动时重用这些元数据 , 从而提高启动速度和减少内存占用 。
1.4 G1 垃圾收集器和 ZGC 功能增强
  1. 在 JDK12 之前,一旦开始执行垃圾收集,即使可能会超过 -XX:MaxGCPauseMillis 参数设定的值,也不会停止 。JDK12 中,如果 G1 垃圾收集器有可能超过预期的暂停时间,则可以终止 。G1 垃圾收集器发现反复标记过多的区域后,G1 就会切换到更增量的一种 Mix GC。它将待回收的集合分为两个部分:强制回收和可选回收 。强制回收的部分是 G1 无法增量回收的部分(比如年轻代)也可以包含能增量回收的部分(比如老年代)来提升性能,它占待回收集合的 80%。当 G1 回收完强制回收部分后,如果还有多余的时间,将会更细粒度的处理可选回收部分 , 每次只会处理一个区域,避免超过用户指定的时间 。在处理完一个区域后,G1 会根据剩余的时间来决定是否继续处理剩余的可选部分 。
  2. JDK12 中,如果应用程序活动非常低,G1 可以使其能够在空闲时自动将 Java 堆内存返还给操作系统 。
  3. JDK13 中,ZGC 也能够主动释放未使用内存给操作系统,但可以通过 -XX : -ZUncommit 参数来显示关闭此功能 。ZGC 支持最大堆大小为 16TB,可以满足大多数大型服务器的需求 。
  4. ZGC 是在 JDK11 中引入的垃圾回收器,但一直都是实验版本,在 JDK15 中正式上线 , 如果你的应用程序需要处理非常大的堆或者更低的暂停时间,那么 ZGC 可能是一个更好的选择 。如果你对兼容性和稳定性有更高的要求,因为 G1 经过长时间的验证和优化,可能 G1 更适合 。
1.5 ShenandoahGC添加一个名为 Shenandoah 的新垃圾收集算法,通过与正在运行的 Java 线程同时进行疏散工作来减少 GC 暂停时间,最终目标旨在针对 JVM 上的内存收回实现低停顿的需求 。


推荐阅读