为什么JVM启动缓慢?
究竟是什么使得JVM(特别是Sun的实现)与其他运行时(如CPython)相比运行速度慢? 我的印象是,它主要是与一大堆图书馆无论是否需要加载,但这似乎是不应该需要10年的时间来解决的。
想想看,JVM的启动时间与Windows上的CLR相比如何呢? 如何Mono的CLR?
更新:我特别关心在Unix中常见的小型实用程序的用例。 Java现在适合这种风格吗? 无论Java的启动开销是多less,是为每个Java进程加起来的,还是开销只在第一个进程中才真正体现?
这里是维基百科在这个问题上 (有一些参考) 要说的 。
看起来大部分时间只是从磁盘加载数据(类)(即启动时间是I / O限制)。
只是要注意一些解决scheme:
有两种机制可以更快地启动JVM。 第一个是Java 6 Update 21以来支持的类数据共享机制(只有HotSpot客户端虚拟机,并且只有串行垃圾回收器据我所知)
要激活它,你需要设置-Xshare (在某些实现上: -Xshareclasses )JVM选项。
要详细了解您可能访问的function: class级数据共享
第二种机制是Java快速入门。 它允许在操作系统启动期间预加载类,请参阅: Java快速入门以获取更多详细信息。
使用1.6(Java 6)客户端JVM运行一个简单的Java应用程序似乎是我的机器上的瞬间。 Sun已经尝试调整客户端JVM以加快启动速度(并且客户端JVM是默认设置),所以如果不需要大量额外的jar文件,启动应该很快。
如果你正在使用Sun公司针对x86_64(64位编译)的HotSpot,请注意当前的实现只能在服务器模式下工作,也就是说,它预先编译了它所加载的每个类,并进行了完全优化,而32位版本也支持客户端模式,并只优化大部分CPU密集型部件,但启动时间更快。
例如见:
- http://en.wikipedia.org/wiki/64-bit#32_vs_64_bit
- http://java.sun.com/docs/hotspot/HotSpotFAQ.html#64bit_compilers
也就是说,至less在我的机器上(64位内核的Linux x86_64),32位HotSpot版本同时支持客户端和服务器模式(通过-client和-server标志),但默认为服务器模式,而64位版本只支持服务器模式。
这真的取决于你在启动过程中所做的事情。 如果您运行Hello World应用程序,我的机器上需要0.15秒。
但是,Java更适合作为客户端或服务器/服务运行,这意味着启动时间不像连接时间(约0.025 ms)或往返时间响应时间(<0.001 ms)那么重要。
有几个原因:
- 大量的
jar
加载 - validation(确保代码不会做坏事)
- JIT(及时编译)开销
我不确定CLR,但是我认为它经常更快,因为它下次caching本地版本的程序集(所以它不需要JIT)。 CPython开始更快,因为它是一个解释器,而IIRC不会做JIT。
除了已经提到的东西(加载类,特别是压缩的JAR)之外; 在HotSpot编译常用字节码之前以解释模式运行; 和HotSpot编译开销,JDK类本身也有相当多的一次性初始化。 许多优化都是为了支持较长时间运行的系统,而启动速度不太受关注。
至于unix风格的stream水线:你当然不希望多次启动和重新启动JVM。 这不会是有效的。 JVM中应该会发生工具链的链接。 除非从JVM中启动这些工具,否则不能轻易地与非Java Unix工具混合使用。
所有具有丰富types系统(例如Java或CLR)的虚拟机与C或C ++中所用的较less丰富的系统相比,不会是一成不变的。 这很大程度上是因为在虚拟机中发生了很多事情,很多类被初始化,并且被运行的系统需要。 初始化系统的快照确实有帮助,但将该映像加载回内存仍然需要花费。
一个简单的hello世界风格与一个主要的一个class轮类仍然需要很多被加载和初始化。 validation类需要大量的依赖性检查和validation,所有这些花费时间和许多CPU指令被执行。 另一方面,一个C程序将不会执行任何这些操作,而只需执行几条指令,然后调用打印机function。