睁开眼睛看看吧,别再说Java启动慢了
之前跟朋友聊天,提到Java 代码运行起来会越来越快、Java 代码需要预热。
"越来越快",看起来是很厉害的样子,但是这句话的另外一个表述方式是:刚刚启动的时候是很慢的。也就是有一个冷启动过程。
冷启动就是指 Java 应用并不是即起即用的,而需要经过虚拟机初始化后才能达到可用状态,再经过程序预热才能达到最佳性能。
然后 Java 语言自从诞生以来就被打上了"慢"的标签,经常听到的一个"自嘲"的言论是:你都用 Java 了,还在乎这点性能?
是的,早早年间 Java 确实慢。然而,经过近 28 年的发展,Java 程序的峰值性能在实时编译(JIT)技术的支持下已经能够超越 C/C++ 程序。
但是实时编译仍然无法解决冷启动速度慢的问题。
这玩意就是一个"命门"了,抓着这一个点就能做出很多文章出来。
在我们传统的单机应用或者通过服务器部署微服务的场景中,这个问题并不明显。
一个原因是应用执行时间足够长,冷启动的问题就被淡化了。第二个原因是我们可以提前将服务预热准备好,以最好的状态迎接用户的服务请求,比如很多框架里面就帮我们做了服务预热的事情。
但是在当下盛行的云原生场景下,当用户的请求源源不断的过来,服务扛不住需要请求支援的时候,我们需要快速的拉起新服务来给到有力的资源。
而"拉起新服务"的这个过程,就涉及到服务的启动,在争分夺秒的情况下,服务的启动时间就显得至关重要。
所以这个冷启动问题使得 Java 在云原生的场景下,无法与 Node.js、Go 等具有快速启动优势的语言竞争。
那么 Java 怎么办呢,怎么去抢占市场呢,难道要依靠强大的生态吃老本、躺平吗?
肯定不会的。
Java 肯定也会在危机中寻求出路,这个出路这就是 Java 的静态编译技术。
这玩意我之前也提到过:Java 静态编译是指将 Java 程序的字节码在单独的离线阶段编译为汇编代码,其输入为 Java 的字节码,输出为操作系统本地原生程序。
静态编译技术 的出现,将 Java 程序提前编译为二进制机器码,实现以 Native Code 的速度启动 Java 程序,带来最多 两个数量级 的启动性能提升。
而该技术代表性的作品就是 GraalVM。
与传统 Java 运行模型相比,GraalVM 的静态编译运行模型有两大特点:
一是静态编译后的可执行程序已经是本地程序,而且自包含了轻量级运行时支持,因此不再额外需要 Java 虚拟机。
没有了 JVM,自然也就消除了冷启动问题,使得应用程序达到即起即用的状态。另外,因为 JVM 的运行也需要消耗一部分内存,去掉 JVM 后应用程序的内存占用也大幅降低。
二是静态编译后的程序也经过了众多的编译优化,运行时不再需要经过解释执行和 JIT 编译,既避免了解释执行的低效,也避免了 JIT 编译的 CPU 开销,还解决了传统 Java 执行模型中无法充分预热,始终存在解释执行的问题,因此可以保证应用程序始终以稳定的性能执行,不会出现性能波动。