如何知道方法是JIT编译还是解释执行的

6

据我了解,没有明确的规则来确定在调用Java方法时是否会进行JIT编译或解释执行。

那么是否有办法告诉JVM我需要某个方法进行JIT编译。并且是否有一种方法可以确定哪些方法会被JIT编译而哪些不会。


2
已编译为本地代码的方法可以被反编译。系统是动态的,更改可能导致编译代码被删除。 - Peter Lawrey
2
Java 也许无法对整个方法进行 JIT。 - bestsss
我很好奇你为什么想知道。 - Tom Hawtin - tackline
回答问题之前过了12年,这可真是够晚的了。我不知道原帖作者的情况,但我需要知道代码是在解释模式下运行还是已编译,因为似乎有些东西强制我的代码进入了解释模式——导致了高 CPU 和低吞吐量,而实际上 Java 并没有做多少事情——所以我想找出到底是什么原因。 - pojo-guy
回答问题之后已经过去了12年,真是无与伦比的速度。我不能代表楼主发言,但我需要知道代码是运行在解释模式还是编译模式下,因为似乎有些东西强制将我的代码转为解释模式——高CPU使用率和低吞吐量,看起来Java实际上并没有做太多事情——而我想找出到底是什么原因导致了这种情况。 - pojo-guy
5个回答

6
据我所知,您无法从JVM内部了解方法是否被JIT编译,也不能强制执行该操作。但是,使用-XX:+PrintCompilation JVM参数,您可以观察JIT编译器的工作,并检查在程序的特定运行中是否对该方法进行了JIT编译。请注意保留HTML标记。

1
有没有办法告诉JVM我需要某个方法被JIT编译?
不,哪些方法被“JITed”和哪些不是由你决定的,实际上,没有任何保证任何方法都会被JIT编译。我建议你把这些决策留给JVM。

1
“JITting”对语义没有影响,只是为了提高性能而进行的实现细节。运行时当然会尝试以最快的方式执行所有代码 - 开发人员认为自己比Hotspot更懂得如何处理类,这种想法是自欺欺人的。 - Andrzej Doyle
非常同意,评论精彩,点赞! - aioobe
嗯,当你开发一个库时,了解一个方法是否被内联、JIT编译等非常重要。了解JVM的工作原理对于编写性能友好的代码至关重要。无法内联一个方法而是通过虚拟表进行分派(这意味着没有循环展开、没有跳过边界检查等)可能会导致速度降低10倍... - bestsss
是的。但关键在于,由于所有层面的复杂性,是否应该对某个方法进行JIT编译、内联等决策,在99.9%的情况下最好由JVM来决定(因为它对此做出这样做的影响有更深入的了解)。 - aioobe
实际上,开发人员应该能够拥有相同的“洞察力”,内联对于非常紧密的循环非常重要(代码的复杂性不会影响最内层的循环)。JVM在较大的方法中内联高度变形的接口存在问题(例如)。当直接内联未发生时,破坏内联缓存也是不好的。仅依赖JVM产生最佳结果并不总是最好的情况,我从不建议任何新手尝试优化代码以使其友好内联,但这对于基于Java的语言或框架开发人员非常重要。 - bestsss

1
有没有办法确切知道哪些方法将被 JIT 编译,哪些不会?
(Oracle)Sun JVM 被称为 HotSpot,这意味着它查看哪些方法被调用最多,因此变得 “热门”,并且那些方法是首先被编译的。因此,某些方法可能永远不会被编译。但是,如果您知道该方法被频繁调用,它很可能会被编译。您可以使用 -XX:CompileThreshold=10000 VM 选项设置阈值,该选项指定需要多少次调用才能将该方法视为“热门”。
我不知道是否有任何方法可以检查当前代码是否在解释模式或编译模式下运行。VM 崩溃日志显示堆栈跟踪中哪些方法是解释的或编译的,也许有一些方法可以在运行时获取它。

0

有一种方法可以要求JVM编译一个类,虽然不能保证它会做任何事情,但应该适用于任何具有JIT的JVM。

Compiler.compileClass(MyClass.class);

0

你无法判断,除非是在HotSpot中出现了错误。术语“JIT”至少已经过时十年。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接