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 を保持するスタック フレームがなくなると、それは "ゾンビ" と宣言されます。

于 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 に答える