Java 为什么JVM启动慢?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/844143/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 20:06:46  来源:igfitidea点击:

Why is the JVM slow to start?

javajvmperformancestartup

提问by Jegschemesch

What exactly makes the JVM (in particular, Sun's implementation) slow to get running compared to other runtimes like CPython? My impression was that it mainly has to do with a boatload of libraries getting loaded whether they're needed or not, but that seems like something that shouldn't take 10 years to fix.

与 CPython 等其他运行时相比,究竟是什么让 JVM(特别是 Sun 的实现)运行缓慢?我的印象是,这主要与无论是否需要加载大量库有关,但这似乎不需要 10 年才能修复。

Come to think of it, how does the JVM start time compare to the CLR on Windows? How about Mono's CLR?

想想看,JVM 启动时间与 Windows 上的 CLR 相比如何?Mono的CLR怎么样?

UPDATE: I'm particularly concerned with the use case of small utilities chained together as is common in Unix. Is Java now suitable for this style? Whatever startup overhead Java incurs, does it add up for every Java process, or does the overhead only really manifest for the first process?

更新:我特别关注在 Unix 中很常见的将小型实用程序链接在一起的用例。Java 现在适合这种风格吗?无论 Java 产生什么启动开销,它是为每个 Java 进程累加起来的,还是仅对第一个进程才真正体现的开销?

采纳答案by Naaff

Here is what Wikipedia has to say on the issue(with some references).

以下是维基百科对这个问题的看法(有一些参考资料)。

It appears that most of the time is taken just loading data (classes) from disk (i.e. startup time is I/O bound).

似乎大部分时间只是从磁盘加载数据(类)(即启动时间受 I/O 限制)。

回答by Zifre

There are a number of reasons:

原因有很多:

  • lots of jars to load
  • verification (making sure code doesn't do evil things)
  • JIT (just in time compilation) overhead
  • 很多jar要加载
  • 验证(确保代码不会做坏事)
  • JIT(即时编译)开销

I'm not sure about the CLR, but I think it is often faster because it caches a native version of assemblies for next time (so it doesn't need to JIT). CPython starts faster because it is an interpreter, and IIRC, doesn't do JIT.

我不确定 CLR,但我认为它通常更快,因为它为下次缓存本机版本的程序集(因此它不需要 JIT)。CPython 启动速度更快,因为它是一个解释器,而 IIRC 不执行 JIT。

回答by jdigital

Running a trivial Java app with the 1.6 (Java 6) client JVM seems instantaneous on my machine. Sun has attempted to tune the client JVM for faster startup (and the client JVM is the default), so if you don't need lots of extra jar files, then startup should be speedy.

在我的机器上,使用 1.6 (Java 6) 客户端 JVM 运行一个简单的 Java 应用程序似乎是即时的。Sun 已尝试调整客户端 JVM 以加快启动速度(并且客户端 JVM 是默认设置),因此如果您不需要大量额外的 jar 文件,那么启动应该很快。

回答by Paggas

If you are using Sun's HotSpot for x86_64 (64bit compiled), note that the current implementation only works in server mode, that is, it precompiles every class it loads with full optimization, whereas the 32bit version also supports client mode, which generally postpones optimization and optimizes the most CPU-intensive parts only, but has faster start-up times.

如果你使用的是Sun的HotSpot for x86_64(64位编译),请注意目前的实现只适用于服务器模式,即对加载的每个类进行全优化预编译,而32位版本也支持客户端模式,一般会推迟优化并仅优化 CPU 密集程度最高的部分,但具有更快的启动时间。

See for instance:

参见例如:

That being said, at least on my machine (Linux x86_64 with 64bit kernel), the 32bit HotSpot version supports both client and server mode (via the -client and -server flags), but defaults to server mode, while the 64bit version only supports server mode.

话虽如此,至少在我的机器上(Linux x86_64 与 64 位内核),32 位 HotSpot 版本支持客户端和服务器模式(通过 -client 和 -server 标志),但默认为服务器模式,而 64 位版本仅支持服务器模式。

回答by StaxMan

In addition to things already mentioned (loading classes, esp. from compressed JARs); running in interpreted mode before HotSpot compiles commonly-used bytecode; and HotSpot compilation overhead, there is also quite a bit of one-time initialization done by JDK classes themselves. Many optimizations are done in favor of longer-running systems where startup speed is less of a concern.

除了已经提到的事情(加载类,尤其是从压缩的 JAR 中);在 HotSpot 编译常用字节码之前以解释模式运行;和 HotSpot 编译开销,还有相当多的一次性初始化由 JDK 类本身完成。许多优化是为了支持运行时间更长的系统,在这些系统中启动速度不太重要。

And as to unix style pipelining: you certainly do NOT want to start and re-start JVM multiple times. That is not going to be efficient. Rather chaining of tools should happen within JVM. This can not be easily intermixed with non-Java Unix tools, except by starting such tools from within JVM.

至于 Unix 风格的流水线:您当然不想多次启动和重新启动 JVM。那不会有效率。相反,工具链应该发生在 JVM 中。这不能很容易地与非 Java Unix 工具混合使用,除非从 JVM 中启动此类工具。

回答by Peter Lawrey

It really depends on what you are doing during the start up. If you run Hello World application it takes 0.15 seconds on my machine.

这实际上取决于您在启动期间正在做什么。如果你在我的机器上运行 Hello World 应用程序需要 0.15 秒。

However, Java is better suited to running as a client or a server/service which means the startup time isn't as important as the connection time (about 0.025 ms) or the round trip time response time (<< 0.001 ms).

但是,Java 更适合作为客户端或服务器/服务运行,这意味着启动时间不如连接时间(约 0.025 毫秒)或往返时间响应时间(<< 0.001 毫秒)重要。

回答by mP.

All VMs with a rich type system such as Java or CLR will not be instanteous when compared to less rich systems such as those found in C or C++. This is largely because a lot is happening in the VM, a lot of classes get initialized and are required by a running system. Snapshots of an initialized system do help but it still costs to load that image back into memory etc.

与不太丰富的系统(如 C 或 C++ 中的系统)相比,所有具有丰富类型系统(如 Java 或 CLR)的 VM 都不会是即时的。这主要是因为在 VM 中发生了很多事情,很多类被初始化并且是运行系统所需要的。初始化系统的快照确实有帮助,但将图像加载回内存等仍然需要成本。

A simple hello world styled one liner class with a main still requires a lot to be loaded and initialized. Verifying the class requires a lot of dependency checking and validation all which cost time and many CPU instructions to be executed. On the other hand a C program will not do any of these and will amount of a few instructions and then invoke the printer function.

一个简单的 hello world 样式的带有 main 的 liner 类仍然需要大量加载和初始化。验证类需要大量的依赖检查和验证,所有这些都需要时间和执行许多 CPU 指令。另一方面,C 程序不会执行任何这些操作,而是会执行一些指令,然后调用打印机功能。

回答by Alexandr

Just to note some solutions:

只是要注意一些解决方案:

There are two mechanisms that allow to faster startup JVM. The first one, is the class data sharing mechanism, that is supported since Java 6 Update 21 (only with the HotSpot Client VM, and only with the serial garbage collector as far as I know)

有两种机制可以更快地启动 JVM。第一个是类数据共享机制,自 Java 6 Update 21 起支持(仅适用于 HotSpot Client VM,据我所知仅适用于串行垃圾收集器)

To activate it you need to set -Xshare(on some implementations: -Xshareclasses) JVM options.

要激活它,您需要设置-Xshare(在某些实现中:-Xshareclasses)JVM 选项。

To read more about the feature you may visit: Class data sharing

要了解有关该功能的更多信息,您可以访问: 班级数据共享

The second mechanism is a Java Quick Starter. It allows to preload classes during OS startup, see: Java Quick Starterfor more details.

第二种机制是 Java Quick Starter。它允许在操作系统启动期间预加载类,请参阅: Java 快速入门了解更多详细信息。