我阅读了一些有关JVM和字节码的资料。我认为如果JVM能够在第一次运行时将字节码转换为平台相关的机器代码,而不是一直解释它们,那将会更有效。
但是,我在项目文件夹中找不到这样的文件。只有bin和src文件夹,其中包含* .class字节码和* .java源代码。
所以我的问题是:
如果Java一直解释字节码,为什么不在第一次运行后将字节码转换为机器码呢?
如果他们确实生成了机器代码,那么文件在哪里?
答案 0 :(得分:4)
答案 1 :(得分:1)
如果Java一直解释字节码,为什么不翻译字节码 在第一次运行后加工代码?
提前(AOT)和及时(JIT)编译都有利弊。
AOT的主要优点是通常允许编译器花费更长的时间,因此它可以执行更复杂的分析和优化。另一个优点是编译器不必在运行时出现在目标机器上。缺点是其他一切。
JIT的主要优点是编译器能够根据仅在运行时知道的信息进行优化。实际上,甚至可以在条件发生变化时优化代码并重新优化代码。此外,与AOT编译器不同,JIT不必浪费时间来优化从未或很少运行的代码。
有些语言的目的是支持一种方法而不是另一种语言。例如,C / C ++是为AOT设计的,而Java是为JIT设计的(虽然可以通过一些限制来编译AOT)。例如,Java非常重视虚拟getter和setter,可能是直到运行时才加载的类。但JIT可以在运行时查看和内联这些函数。相比之下,如果您在C ++中对每个字段访问使用虚方法,则会给性能带来巨大的损失。
答案 2 :(得分:0)
它不会一直解释代码。经过一段时间后,解释的代码将被转换为字节代码。您可以使用-XX:CompileThreshold =(默认值为10000)调整此“时间”,也可以完全关闭编译。
在记忆中。内存中有一个叫做“代码缓存”的特殊区域。您可以使用-XX:+ PrintCompilation查看编译到缓存中的方法以及如何从缓存中清除这些方法。缓存的大小也是可配置的,请参阅-XX:ReservedCodeCacheSize =。
答案 3 :(得分:0)
嗯,JVM有预处理数据,但只针对自己的类。鉴于JRE库的大小以及它通常不会改变的事实,这是一个很大的胜利(你可能会寻找名为classes.jsa
的文件)。
但是,即使这些文件不包含本机代码,也只包含更易于处理的字节代码。
热点JVM中代码生成的重点是,他们不会像您想象的那样在类或方法的基础上编译代码。这些JVM在自我分析期间发现交互时编译跨越多个交互方法的代码片段。这些代码块可能跨越JRE中的方法,扩展库,类路径中的第三方库以及应用程序类,因此仅对此特定组合有效。
在编辑过程中,将使用收集的有关您的计划行为的信息,例如未采用的代码路径可能会被省略,并且可能会声明条件以评估某个结果,就像它们在之前的评估中所做的那样。这会产生很高的性能,但是当一个断言不再存在时,JVM必须在相同的执行中删除代码,例如,程序可能会采用它之前没有的代码路径,或者已经将新类加载到JVM中,这扩展了一个代码已经优化的类,如果没有子类,等等。
因此,即使在同一环境中,优化和编译的代码可能会被淘汰,但在下一次执行中,它甚至更有可能被淘汰。最后,JVM必须检查旧代码是否仍然合适,这可能比简单地收集新环境的数据和程序行为更加昂贵。