42

在运行 Java 1.6 (1.6.0_03-b05) 应用程序时,我添加了-XX:+PrintCompilation标志。在某些方法的输出上,特别是我知道的一些方法被调用了很多,我看到了文本made not entrantmade 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]
4

4 回答 4

23

我已经在我的博客上收集了一些关于此的信息。我发现的 Cliff Click 评论说:

僵尸方法是其代码因类加载而无效的方法。通常,服务器编译器会对非最终方法做出积极的内联决策。只要内联方法从未被覆盖,代码就是正确的。当一个子类被加载并且方法被覆盖时,编译后的代码会被中断,以供将来调用它。代码被声明为“不可进入”(没有未来的调用者对损坏的代码),但有时现有的调用者可以继续使用该代码。在内联的情况下,这还不够好;当现有调用者的堆栈帧从嵌套调用返回到代码时(或者仅当它们在代码中运行时),它们的堆栈帧将被“取消优化”。当没有更多的堆栈帧将 PC 保存在损坏的代码中时,它就被宣布为“僵尸”——一旦 GC 处理它,就可以将其移除。

于 2011-08-21T11:52:23.763 回答
9

这对我来说绝对不是一个专业领域,但我很感兴趣,所以做了一些挖掘。

您可能会发现一些有趣的链接:OpenJDK:nmethod.cppOpenJDK: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); }
//...

只是作为一个起点。

于 2010-05-31T14:12:02.803 回答
7

更新的解释是日志中可以有这样的条目:

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下编译,然后在 tier level 下4它得到了进一步的优化,并且它已被禁止进入3-d 层;这意味着它将被第 4 层的代码替换。

于 2018-03-11T20:28:09.100 回答
3

这是一个 Gist,其中包含令人难以置信的大量信息PrintCompilation。具体来说,它说:

当去优化发生时,如果决定使违规行为无效nmethod,将首先“设为不可进入”;然后,当NMethodSweeper发现堆栈上不再有它的激活时,它是“僵尸”;

于 2016-02-26T10:21:54.457 回答