63

与 CPython 等其他运行时相比,究竟是什么让 JVM(尤其是 Sun 的实现)运行缓慢?我的印象是,这主要与大量库是否需要加载有关,但这似乎不需要 10 年的时间来解决。

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

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

4

8 回答 8

22

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

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

于 2009-05-09T22:07:38.377 回答
8

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

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

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

要阅读有关您可能访问的功能的更多信息: 课堂数据共享

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

于 2013-02-04T07:53:16.800 回答
5

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

于 2009-05-09T22:22:12.773 回答
4

如果您使用 Sun 的 HotSpot for x86_64(64 位编译),请注意当前实现仅在服务器模式下工作,也就是说,它预编译加载的每个类并进行完全优化,而 32 位版本还支持客户端模式,这通常会推迟优化并仅优化 CPU 密集程度最高的部分,但启动时间更快。

参见例如:

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

于 2009-05-09T23:12:12.840 回答
3

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

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

于 2009-05-10T07:30:40.193 回答
1

有几个原因:

  • 有很多jar要加载的
  • 验证(确保代码不会做坏事)
  • JIT(即时编译)开销

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

于 2009-05-09T22:07:21.870 回答
1

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

至于 unix 风格的流水线:您当然不想多次启动和重新启动 JVM。这不会是有效的。工具链应该发生在 JVM 中。这不能轻易地与非 Java Unix 工具混合,除非从 JVM 中启动这些工具。

于 2009-05-10T01:58:39.990 回答
0

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

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

于 2009-05-10T07:39:43.180 回答