从Java 8升级的原因

2021-04-15 23:59:18

句法糖(如var的引入)往往不足以让某人(特别是非开发人员)说服前进。这是java 8,近7年后的第一个释放近7年的原因之一,仍然被广泛使用。然而,许多事情与语法不同。当他们考虑到所有这些时,它可能会发现您可以再运行Java 8。否,我不用映射代码,但只需更新用作运行时使用的JVM!

让'概述升级JVM的一些非句法好处。对于仍然在Java 8上运行的人来说,他们可能成为关于改变的良好起点。对于已经迁移的人,他们可能会介绍最近的JVM的一些不那么明显的特征。

注意:在本文中,我使用条款' java'和#39; JVM'关于Hotspot VM

即使是最简单的地狱世界!应用程序需要一些时间开始(在调用java -jar之间经过...并打印消息)。最近的比较显示,因为Java 8申请启动时间几乎减半(与Java 16的早期构建相比),始终如一地进步更好的性能。虽然该部件仅在JVM级别本身上引入的许多优化时,占第二秒(或至少应该是应该的)的分数。换句话说,在最新的JVM上运行的相同应用程序应比在Java 8上运行时更快地开始。

为了验证这一点,我拍了一个现实生活,中等大小的春靴2.3在Kotlin编写的应用程序(JVMTarget =' 1.8'目标Java 8字节码),并使用Java 8运行它, 11和15.作为启动时间测量,I' ve选自春天启动本身在日志中报告的值。虽然它不是最好的起始时间的最佳衡量标准(在这种情况下Quarkus'方法似乎更好),它应该足够好,以便在更改唯一改变的是JVM运行时进行比较。

如您所见,从Java 8到11切换为15%的加速(1秒更快)。由于某种原因,Java 15结果与11(约〜200ms)有点慢,但它仍然可以通过Java 8提供至少12%的改进。

为什么这很重要?在分布式(已复制的)环境中,更快的启动意味着其他节点必须在更短的时间段内生存更高的负载(由临时减少的储副副本的数量)。这降低了意外的服务停机时间甚至整个系统的级联失败的可能性。此外,更快的启动允许更快地执行系统升级并具有更高的可靠性。这意味着他们只是减少中断可能性。

现代Hotspot JVM至少有4种类型的垃圾收集器(GC),用于生产使用:

注意:还有一个名为epsilon的NO-OP GC,但这是针对各种测试的目的。

从Java 9开始,默认的垃圾收集器已从Parally更改为G1。两个GC的详细比较远远超出了这篇文章的范围,但简而言之,G1阻止了应用线程频繁(所谓的"停止 - 世界"阶段),导致GC暂停较短。通常,当允许吞吐量的响应时间时,G1应该是更好的合适。

为什么一个人应该关心gc暂停?有一件事显然是更好的应用响应能力。暂停暂停第二个或更多(在高负载下并行GC不少数)可能不仅可以产生负面影响用户体验,而且还导致依赖服务的失败(例如,通过耗尽它们的连接池)或意外的应用程序重启(由于GC暂停时应用程序将被识别为非响应者)。

那个'肯定是真实的,但G1' S稳定性&每次新版本都会改​​善性能。只有一些更改(重要的错误修正)仍然被返回 - 简单地,Java 8不提供G1的最佳体验,它永远不会提供。

这同样适用于几乎所有的变化或改进都被回到Java 8(如U191所介绍的初始容器意识):即使是重要的,它也会提供与较新的JVMS的相同程度的经验。

有趣的是,最近的JVM版本具有另一个有用的功能 - 基于资源约束(CPU,内存)自动在串行和G1 GC之间切换的能力。该想法基于两个收集器的特征 - 当在具有有限资源的环境中操作(例如,单CPU或低存储器环境)串行时,单线程GC通常是比任何多线程更好的选择。

这似乎是一个有效的底层热点功能,因为我没有找到这种选择的任何特定标准。但是,根据我的Java 11看起来像是这样的,那就是:

通过多个CPU,当环境具有小于1792 MB的可用内存时,正在选择串行收集器。

在Java 8上运行时,无论环境资源约束如何,都将使用并行GC。当多线程能力有限时,这可能变得尤其疼痛(例如,单CPU)。在这种情况下,启动多个GC线程只会导致额外的上下文切换有效地减慢处理。

适当的GC选择是自己的巨大主题,所以让'得出结论,最近的JVM版本提供了比以前更合适的默认值。

从Java 8升级并不总是必须从代码的更改开始。 Java不仅仅是一种语言,而且JVM经历了每个新版本的重大变化和改进。只需将运行时间切换到较新版本,应导致启动时间减少,更好的垃圾收集&表现更高。所有这些功能也应该在可靠性方面带来好处。虽然最近的一些功能已经被回到Java 8,但它们可以竞争更近期的经验水平。远离Java 8不是'如果'再过,但只有关于'何时'