java printcompile输出:“made not entrant”和“made zombie”的含义是什么?

时间:2023-01-23 17:19:28

When running a Java 1.6 (1.6.0_03-b05) app I've added the -XX:+PrintCompilation flag. On the output for some methods, in particular some of those that I know are getting called a lot, I see the text made not entrant and made zombie.

在运行Java 1.6 (1.6.0_03-b05)应用程序时,我添加了-XX:+ printcompile标志。在一些方法的输出中,特别是一些我知道会被经常调用的方法,我看到文本变成了not entrant,变成了zombie。

What do these mean? Best guess is that it's a decompilation step before recompiling either that method or a dependency with greater optimisation. Is that true? Why "zombie" and "entrant"?

这些是什么意思?最好的猜测是,在重新编译该方法或具有更大优化的依赖项之前,这是一个反编译步骤。这是真的吗?为什么“僵尸”和“竞争者”?

Example, with quite a bit of time between some of these lines:

举个例子,在这几行之间有一段时间:

[... 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 个解决方案

#1


22  

I've pulled together some info on this on my blog. A Cliff Click comment I found says:

我在博客上收集了一些相关信息。我找到的一个Cliff Click评论说:

Zombie methods are methods whose code has been made invalid by class loading. Generally the server compiler makes aggressive inlining decisions of non-final methods. As long as the inlined method is never overridden the code is correct. When a subclass is loaded and the method overridden, the compiled code is broken for all future calls to it. The code gets declared "not entrant" (no future callers to the broken code), but sometimes existing callers can keep using the code. In the case of inlining, that's not good enough; existing callers' stack frames are "deoptimized" when they return to the code from nested calls (or just if they are running in the code). When no more stack frames hold PC's into the broken code it's declared a "zombie" - ready for removal once the GC gets around to it.

僵尸方法是其代码被类装入无效的方法。通常,服务器编译器会对非最终方法进行内联决策。只要内联方法不被重写,代码就是正确的。当加载一个子类并覆盖该方法时,编译后的代码将被破坏,以便以后调用它。代码被声明为“not entrant”(将来不会调用被破坏的代码),但是有时现有的调用者可以继续使用代码。对于内联,这还不够好;当它们返回到嵌套调用的代码(或者只是在代码中运行)时,现有的调用者的堆栈帧会被“优化”。当不再有堆栈帧将PC保存到被破坏的代码中时,它就会被声明为“僵尸”——一旦GC开始处理它,就会被删除。

#2


9  

This is absolutely not an area of expertise for me, but I was interested and so did a bit of digging.

这绝对不是我的专业领域,但我很感兴趣,所以我也做了一些挖掘工作。

A couple of links you might find interesting: OpenJDK:nmethod.cpp, OpenJDK:nmethod.hpp.

您可能会发现一些有趣的链接:OpenJDK:nmethod。cpp OpenJDK:nmethod.hpp。

A excerpt of 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); }
//...

Just as a starting place.

就像一个起点。

#3


2  

A newer explanation is that there can be entries like this in log:

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

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

This actually means that one method (second here) has been compiled under tier level 3, then under tier level 4 it has been further more optimized and it has been made not entrant for the 3-d tier; meaning it will be replaced with code from the 4-th tier.

这实际上意味着一个方法(这里的第二个方法)已经在第3层编译,然后在第4层它已经被进一步优化,它已经不再是3d层的入口;这意味着它将被第4层的代码所取代。

#4


1  

Here is a Gist with an unbelievable amount of information on PrintCompilation. Specifically, it says:

这里有一个要点,关于版画的大量信息。具体地说,它说:

When deoptimization happens, if it is decided to invalidate the offending nmethod, it will be "made not entrant" first; and then, when the NMethodSweeper finds that there are no activations of it on the stacks any more, it is "made zombie";

当发生反优化时,如果决定使违规的nmethod无效,则首先将其改为“not entrant”;然后,当NMethodSweeper发现栈上不再有它的激活时,它就变成了“僵尸”;

#1


22  

I've pulled together some info on this on my blog. A Cliff Click comment I found says:

我在博客上收集了一些相关信息。我找到的一个Cliff Click评论说:

Zombie methods are methods whose code has been made invalid by class loading. Generally the server compiler makes aggressive inlining decisions of non-final methods. As long as the inlined method is never overridden the code is correct. When a subclass is loaded and the method overridden, the compiled code is broken for all future calls to it. The code gets declared "not entrant" (no future callers to the broken code), but sometimes existing callers can keep using the code. In the case of inlining, that's not good enough; existing callers' stack frames are "deoptimized" when they return to the code from nested calls (or just if they are running in the code). When no more stack frames hold PC's into the broken code it's declared a "zombie" - ready for removal once the GC gets around to it.

僵尸方法是其代码被类装入无效的方法。通常,服务器编译器会对非最终方法进行内联决策。只要内联方法不被重写,代码就是正确的。当加载一个子类并覆盖该方法时,编译后的代码将被破坏,以便以后调用它。代码被声明为“not entrant”(将来不会调用被破坏的代码),但是有时现有的调用者可以继续使用代码。对于内联,这还不够好;当它们返回到嵌套调用的代码(或者只是在代码中运行)时,现有的调用者的堆栈帧会被“优化”。当不再有堆栈帧将PC保存到被破坏的代码中时,它就会被声明为“僵尸”——一旦GC开始处理它,就会被删除。

#2


9  

This is absolutely not an area of expertise for me, but I was interested and so did a bit of digging.

这绝对不是我的专业领域,但我很感兴趣,所以我也做了一些挖掘工作。

A couple of links you might find interesting: OpenJDK:nmethod.cpp, OpenJDK:nmethod.hpp.

您可能会发现一些有趣的链接:OpenJDK:nmethod。cpp OpenJDK:nmethod.hpp。

A excerpt of 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); }
//...

Just as a starting place.

就像一个起点。

#3


2  

A newer explanation is that there can be entries like this in log:

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

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

This actually means that one method (second here) has been compiled under tier level 3, then under tier level 4 it has been further more optimized and it has been made not entrant for the 3-d tier; meaning it will be replaced with code from the 4-th tier.

这实际上意味着一个方法(这里的第二个方法)已经在第3层编译,然后在第4层它已经被进一步优化,它已经不再是3d层的入口;这意味着它将被第4层的代码所取代。

#4


1  

Here is a Gist with an unbelievable amount of information on PrintCompilation. Specifically, it says:

这里有一个要点,关于版画的大量信息。具体地说,它说:

When deoptimization happens, if it is decided to invalidate the offending nmethod, it will be "made not entrant" first; and then, when the NMethodSweeper finds that there are no activations of it on the stacks any more, it is "made zombie";

当发生反优化时,如果决定使违规的nmethod无效,则首先将其改为“not entrant”;然后,当NMethodSweeper发现栈上不再有它的激活时,它就变成了“僵尸”;