我知道JIT编译是使用热点机制编译到本机代码,因为它是对操作系统,Hardwards等的优化,所以非常快。
我的问题是,为什么Java不将JIT编译的代码存储在文件中的某个位置并将其用于将来的目的?这也可以减少“初始预热”时间。
请告诉我这里缺少的东西。
添加到我的问题: 为什么Java不将完整代码编译为native并始终使用(对于特定的JVM,OS,平台)?为何选择JIT?
答案 0 :(得分:3)
虽然可以保证您将始终使用JVM,但无法保证始终使用相同的JVM。热点优化代码仅对您的计算机有效。
使用Java,无法保证代码是JVM的本地代码。 Applet就是一个很好的例子,Webstart也说明了这一点。通用的“保持优化”只会在很少运行的代码中混淆缓存,并且在哪里保留优化的扩展会产生问题。
知道保留磁盘缓存需要多长时间也会产生很大的难题,而且你不必重新编译'class'文件来验证缓存是否适用于类的正确“发布”文件?除了可选的串行版本uid之外,Java没有相同类文件指示符的“此版本”。
也许通过检查汇总类文件并将其放在已编译类的字段中有一个解决方法,但我不想考虑一个JVM的启动时间,该任务是扫描所有缓存的机器特定代码,构建表,干预类加载器,并使用优化的代码检查加载的类的校验和。
答案 1 :(得分:2)
我自己也问过这个问题。我得到的印象是很难做到正确,并避免有一个包含过期代码的商店。
解决这个问题的一个方法是做一个-XX:+PrintCompilation
并编写一个简短的预热例程来加热这些方法。
答案 2 :(得分:2)
如果我没记错的话,已经尝试过缓存和共享JIT编译的代码,并且发现这不是一个好主意。
一方面,现代HotSpot JIT编译器在当前CPU模型的上下文中生成并优化代码,以及当前执行的使用模式。如果要缓存已编译的代码,那么代码很可能不是最佳的。
另一方面,显然存在各种欺骗技术问题。例如,缓存的代码成为潜在的安全漏洞。例如,代码区域需要由共享它的所有应用程序/用户写入。但这意味着一个用户可能会干扰另一个用户的应用程序的运行。
答案 3 :(得分:2)
它存在于.Net(在许多方面类似于java),它被称为NGEN。所以我不明白为什么它在java中不存在。
我可以看到为什么没有这样做的两个原因:
答案 4 :(得分:2)
某些JVM(如IBM的JVM)确实有“ahead of time shared JIT code”。这很难做到(正如其他答案所指出的那样),因为一个JVM一次使用的类文件可能与下次使用的类文件不同,即使它们具有相同的名称。因此,需要很多逻辑来证明“我之前看到的A类与我现在拥有的A类真的相同”。
另一个问题是JITed代码通常包含特定于地址空间的值(例如:给定静态变量的地址,或另一个JITed方法的入口点)以及那些可以(当然会!)在每个JVM上更改的值因此,在处理这些问题时必须小心谨慎。
AOT代码提供的性能优势是真实的,并且该功能非常值得使用,具体取决于具体情况。 (具体来说:事情不会改变运行等等... - 比如调用相同版本的app服务器,或者Eclipse,例如)