运行Java 1.6(1.6.0_03-b05)应用程序时,我添加了-XX:+PrintCompilation
标志。在某些方法的输出中,特别是我知道的一些方法被大量调用,我看到了文本made not entrant
和made zombie
。
这些是什么意思?最好的猜测是,在重新编译该方法或具有更高优化的依赖项之前,它是一个反编译步骤。真的吗?为什么“僵尸”和“参赛者”?
示例,其中一些行之间有相当长的时间:
[... near the beginning]
42 jsr166y.LinkedTransferQueue::xfer (294 bytes)
[... much later]
42 made not entrant jsr166y.LinkedTransferQueue::xfer (294 bytes)
--- n sun.misc.Unsafe::compareAndSwapObject
170 jsr166y.LinkedTransferQueue::xfer (294 bytes)
170 made not entrant jsr166y.LinkedTransferQueue::xfer (294 bytes)
4% jsr166y.LinkedTransferQueue::xfer @ 29 (294 bytes)
171 jsr166y.LinkedTransferQueue::xfer (294 bytes)
[... even later]
42 made zombie jsr166y.LinkedTransferQueue::xfer (294 bytes)
170 made zombie jsr166y.LinkedTransferQueue::xfer (294 bytes)
171 made not entrant jsr166y.LinkedTransferQueue::xfer (294 bytes)
172 jsr166y.LinkedTransferQueue::xfer (294 bytes)
[... no further logs]
答案 0 :(得分:23)
我在my blog上汇总了一些相关信息。我找到的Cliff Click评论说:
Zombie方法是通过类加载使代码无效的方法。通常,服务器编译器会对非最终方法做出积极的内联决策。只要内联方法永远不会被覆盖,代码就是正确的。当加载子类并重写该方法时,编译的代码将被中断,以便将来调用它。代码被声明为“not entrant”(没有未来的调用者来破坏代码),但有时现有的调用者可以继续使用代码。在内联的情况下,这不够好;当现有调用者的堆栈帧从嵌套调用返回代码时(或者只是它们在代码中运行时)被“去优化”。当没有更多的堆栈帧将PC保存到损坏的代码中时,它被声明为“僵尸” - 一旦GC到达它就可以移除它。
答案 1 :(得分:9)
这对我来说绝对不是一个专业领域,但我很感兴趣,所以做了一些挖掘。
您可能会发现一些有趣的链接:OpenJDK:nmethod.cpp,OpenJDK:nmethod.hpp。
摘录nmethod.hpp
:
// Make the nmethod non entrant. The nmethod will continue to be
// alive. It is used when an uncommon trap happens. Returns true
// if this thread changed the state of the nmethod or false if
// another thread performed the transition.
bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); }
//...
就像一个起点。
答案 2 :(得分:6)
更新的解释是在日志中可以有这样的条目:
129 72 3 EscapeAnalysysTest::second (24 bytes)
.......... some more lines
135 76 4 EscapeAnalysysTest::second (24 bytes)
137 74 3 EscapeAnalysysTest::second (24 bytes) made not entrant
这实际上意味着一个方法(此处为second
已在tier level 3下编译,然后在层级4
下进行了进一步优化,它已被非参赛者用于3-d层;意味着它将被替换为第4层的代码。
答案 3 :(得分:2)
Here is a Gist在PrintCompilation
上提供了令人难以置信的大量信息。具体来说,它说:
当进行去优化时,如果决定使有问题的
nmethod
无效,那么它将首先“不进入”;然后,当NMethodSweeper
发现堆栈上没有激活它时,它就是“制造僵尸”;