これまでのところ、Java コードの問題を分析するための最も効果的なツールは依然として Java スレッド ダンプだと思います。理由は次のとおりです:
1. これは、どのオペレーティング システム プラットフォームでも使用できます。
2. ほとんどの場合、実稼働環境で使用できます。
3. オペレーティング システムによって提供されるツールと比較して、Java スレッド ダンプによって提供される情報は単純であり、アプリケーション コードに直接対応しています。
4. 分析対象のシステムへの干渉がほとんどないため、実際の問題を反映できます。他の多くのプロファイリング ツールや計測ツール自体は、JVM の動作に大きな干渉を及ぼし、実際の問題を明らかにできないことが多く、そのようなツールは運用システムでは使用できません。
通常の状況では、メモリ リークよりも Java 仮想マシンのデッドロックを分析する方がはるかに簡単だと思います。デッドロックが発生すると、通常、JVM は一時停止状態 (ハング) になり、スレッド ダンプから静的で安定した情報が得られるため、デッドロックを見つけるには、問題のスレッドを見つけるだけで済みます。メモリ リークの問題は定義が困難です。実行中の JVM には無数のオブジェクトが存在します。どのオブジェクトがゴミでどれがそうでないかは、プログラムを書いた人だけが知っています。さらに、オブジェクトの参照関係は非常に複雑で、把握するのが困難です。明確な定義、オブジェクト参照グラフ。
Java 仮想マシンのデッドロックが発生すると、仮想マシンの CPU 使用率がゼロになり、すぐに top または prstat の出力から消えることがオペレーティング システムから観察されます。この時点で、スレッド ダンプを収集できます。Unix/Linux の場合は、kill -3
Java スレッド ダンプを取得したら、「モニター エントリを待機している」スレッドを見つけるだけです。同じアドレスでロックを待機しているスレッドが多数ある場合 (Java の場合、オブジェクト (ロック) に対してスレッドが 1 つしかない場合、これはデッドロックが発生する可能性があることを示します。例:
"service-j2ee" prio=5 tid=0x024f1c28 nid=0x125 waiting for monitor entry [62a3e000..62a3f690] [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.internalGetResource(IASNonS haredResourcePool.java:625) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - waiting to lock <0x965d8110> (a com.sun.enterprise.resource.IASNonSharedResourcePool) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.getResource(IASNonSharedRes ourcePool.java:520) ................
問題を特定するには、多くの場合、2 分後に再度スレッド ダンプを収集する必要があります。取得された出力が同じで、まだ多数のスレッドが存在する場合は、同じアドレスをロックするのを待っている場合、デッドロックになっているはずです。
現在ロックを保持しているスレッドを見つける方法が問題解決の鍵となります。その方法は、スレッド ダンプを検索し、「locked <0x965d8110>」を探し、ロックを保持しているスレッドを見つけることです。
[27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: "Thread-20" daemon prio=5 tid=0x01394f18 nid=0x109 runnable [6716f000..6716fc28] [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.net.SocketInputStream.socketRead0(Native Method) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.net.SocketInputStream.read(SocketInputStream.java:129) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.Packet.receive(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.DataPacket.receive(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.getNextPacket(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.read(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.read(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.net.ns.NetInputStream.read(Unknown Source) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.MAREngine.unmarshalUB1(MAREngine.java:929) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.MAREngine.unmarshalSB1(MAREngine.java:893) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.Ocommoncall.receive(Ocommoncall.java:106) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.ttc7.TTC7Protocol.logoff(TTC7Protocol.java:396) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x954f47a0> (a oracle.jdbc.ttc7.TTC7Protocol) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at oracle.jdbc.driver.OracleConnection.close(OracleConnection.java:1518) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x954f4520> (a oracle.jdbc.driver.OracleConnection) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.JdbcUrlAllocator.destroyResource(JdbcUrlAllocator.java:122) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.destroyResource(IASNonSharedResourcePool.java:8 72) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool.resizePool(IASNonSharedResourcePool.java:1086) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: - locked <0x965d8110> (a com.sun.enterprise.resource.IASNonSharedResourcePool) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at com.sun.enterprise.resource.IASNonSharedResourcePool$Resizer.run(IASNonSharedResourcePool.java:1178) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.util.TimerThread.mainLoop(Timer.java:432) [27/Jun/2006:10:03:08] WARNING (26140): CORE3283: stderr: at java.util.TimerThread.run(Timer.java:382)
この例では、ロックを保持しているスレッドは Oracle が結果を返すのを待っていますが、応答を待つことができないため、デッドロックが発生します。
ロックを保持しているスレッドがまだ別のオブジェクトのロックを待機している場合は、デッドロックの原因が見つかるまで上記の方法に従います。
さらに、このようなスレッドはスレッド ダンプでよく見られますが、条件を待って積極的にロックを放棄するスレッドです。
例:
"Thread-1" daemon prio=5 tid=0x014e97a8 nid=0x80 in Object.wait() [68c6f000..68c6fc28] at java.lang.Object.wait(Native Method) - waiting on <0x95b07178> (a java.util.LinkedList) at com.iplanet.ias.util.collection.BlockingQueue.remove(BlockingQueue.java:258) - locked <0x95b07178> (a java.util.LinkedList) at com.iplanet.ias.util.threadpool.FastThreadPool$ThreadPoolThread.run(FastThreadPool.java:241) at java.lang.Thread.run(Thread.java:534)
このタイプのスレッド、特にスレッドの待機状態の分析が必要になる場合があります。
実際、Java スレッド ダンプはデッドロックの分析に使用されるだけではなく、Java アプリケーション実行時のその他の奇妙な動作もスレッド ダンプを使用して分析できます。
***、Java SE 5ではjstackツールが追加され、スレッドダンプも取得できるようになりました。 Java SE 6 では、jconsole のグラフィカル ツールを使用して、オブジェクト モニターと java.util.concurrent.locks に関連するデッドロックを簡単に見つけることもできます。
以上がJava 仮想マシンがデッドロックを実装する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。