Javaスレッドダンプを分析する方法


100

私はjavaについて、特にメモリ管理とスレッドについてもっと理解しようとしています。このため、最近スレッドダンプを調べることに興味を持ちました。

以下は、Java用の組み込みツールであるVisualVMを使用してWebアプリから取得した数行です。

"Finalizer" daemon prio=8 tid=0x02b3d000 nid=0x898 in Object.wait() [0x02d0f000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118)
    - locked <0x27ef0288> (a java.lang.ref.ReferenceQueue$Lock)
    at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:134)
    at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

   Locked ownable synchronizers:
    - None

"Reference Handler" daemon prio=10 tid=0x02b3b800 nid=0x494 in Object.wait() [0x02cbf000]
   java.lang.Thread.State: WAITING (on object monitor)
    at java.lang.Object.wait(Native Method)
    - waiting on <0x27ef0310> (a java.lang.ref.Reference$Lock)
    at java.lang.Object.wait(Object.java:485)
    at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:116)
    - locked <0x27ef0310> (a java.lang.ref.Reference$Lock)

まず、いくつかの変数名について質問があります。

  • tidとnidはどういう意味ですか?
  • Object.waitの後の括弧内の数字は何ですか?

次に、スタックトレース自体について:

  • <.....>(java.lang ....)で待機することの意味と<..>の数字は何ですか
  • ロックとはどういう意味ですか<.....>(java.lang ....)同じ質問、<..>には何があります

「ロック」という言葉は何らかの形で待ち状態に関係していると思いましたが、私は間違っていました。実際、なぜロックが3回繰り返されるのか疑問に思っていますが、同じダンプにあるように、スレッドは実行可能な状態です。

"Thread-0" prio=6 tid=0x02ee3800 nid=0xc1c runnable [0x03eaf000]
   java.lang.Thread.State: RUNNABLE
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:199)
    at java.io.BufferedInputStream.read1(BufferedInputStream.java:256)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:317)
    - locked <0x23963378> (a java.io.BufferedInputStream)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    - locked <0x23968450> (a java.io.InputStreamReader)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    - locked <0x23968450> (a java.io.InputStreamReader)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at org.codehaus.plexus.util.cli.StreamPumper.run(StreamPumper.java:145)

最後に、これが最悪でした。

"CompilerThread0" daemon prio=10 tid=0x02b81000 nid=0x698 waiting on condition [0x00000000]
   java.lang.Thread.State: RUNNABLE

このスレッドは実行可能な状態ですが、条件待ちです。0x00000の状態とは何ですか?

スタッククラスがスレッドクラスの形跡がないほど短いのはなぜですか?

私のすべての質問にあなたが答えてくれるなら、私はとても感謝しています。

ありがとう

回答:


113

TIDはthead idで、NIDはネイティブスレッドIDです。このIDはプラットフォームに大きく依存します。jstackスレッドダンプのNIDです。Windowsでは、これは単にプロセス内のOSレベルのスレッドIDです。LinuxおよびSolarisでは、これはスレッドのPIDです(これは軽量のプロセスです)。Mac OS Xでは、これはネイティブのpthread_t値であると言われています。

このリンクにアクセスしてください:JavaレベルのスレッドID:これら2つの用語の定義と詳細な説明については。

IBMのサイトで次のリンクを見つけました:スレッドダンプの解釈方法。これについて詳しく説明します。

これは、待機の意味を説明しています。ロックにより、複数のエンティティが共有リソースにアクセスできなくなります。Java™の各オブジェクトには、関連付けられたロックがあります(同期されたブロックまたはメソッドを使用して取得)。JVMの場合、スレッドはJVM内のさまざまなリソースを求めて競合し、Javaオブジェクトをロックします。

次に、モニターを、スレッド間の柔軟な同期を可能にするためにJVMで使用される特殊なロックメカニズムとして説明します。このセクションでは、モニターとロックを同じ意味で読んでください。

次に、さらに進みます。

すべてのオブジェクトにモニターが表示されないようにするために、JVMは通常、クラスまたはメソッドブロックのフラグを使用して、アイテムがロックされていることを示します。ほとんどの場合、コードの一部は競合なしでロックされたセクションを通過します。したがって、このコードを保護するには、ガーディアンフラグで十分です。これはフラットモニターと呼ばれます。ただし、別のスレッドがロックされているコードにアクセスしたい場合は、本物の競合が発生しています。JVMは、2番目のスレッドを保持し、コードセクションへのアクセスを調整するためのシグナリングメカニズムを準備するために、監視オブジェクトを作成(または拡張)する必要があります。このモニターは現在、インフレートモニターと呼ばれています。

これは、スレッドダンプの行に表示される内容のより詳細な説明です。Javaスレッドは、オペレーティングシステムのネイティブスレッドによって実装されます。各スレッドは、次のような太字の行で表されます。

「スレッド1」(TID:0x9017A0、sys_thread_t:0x23EAC8、状態:R、ネイティブID:0x6E4)prio = 5

*次の6つの項目は、例の括弧内の値と一致させているため、これについて説明しています[]:

  1. 名前[ スレッド1 ]、
  2. 識別子[ 0x9017A0 ]、
  3. JVMデータ構造アドレス[ 0x23EAC8 ]、
  4. 現在の状態[ R ]、
  5. ネイティブスレッド識別子[ 0x6E4 ]、
  6. および優先度[ 5 ]。

「待機」は、アプリケーションスレッド自体ではなく、jvm自体に関連付けられたデーモンスレッドのように見えます。「in Object.wait()」を取得すると、デーモンスレッド(ここでは「ファイナライザ」)がオブジェクトのロックに関する通知を待機していることを意味します。この場合、待機している通知が表示されます。 <0x27ef0288>を待機しています(java.lang.ref.ReferenceQueue $ Lock) "

ReferenceQueueの定義は次のとおりです。適切な到達可能性の変更が検出された後、登録された参照オブジェクトがガベージコレクターによって追加される参照キュー。

ファイナライザスレッドが実行されると、ガベージコレクションが動作して、オブジェクトに関連付けられているリソースをクリーンアップします。私がそれを正しく見ている場合、javaオブジェクトがメソッドを実行しているため、ファイナライザスレッドはそのオブジェクトが現在のタスクで終了するまでロックされます。

また、ファイナライザはメモリを再利用するだけでなく、リソースのクリーンアップよりも複雑になります。私はそれについてもっと研究する必要がありますが、オブジェクトのメソッドに関連するファイルを開いている、ソケットなどがある場合、ファイナライザはそれらのアイテムを解放することにも取り組んでいます。

スレッドダンプでObject.waitを実行した後の括弧内の数字は何ですか?

スレッドへのメモリ内のポインタです。これはより詳細な説明です:

C.4.1スレッド情報

スレッドセクションの最初の部分には、次のように、致命的なエラーを引き起こしたスレッドが表示されます。

Current thread (0x0805ac88):  JavaThread "main" [_thread_in_native, id=21139]
                    |             |         |            |          +-- ID
                    |             |         |            +------------- state
                    |             |         +-------------------------- name
                    |             +------------------------------------ type
                    +-------------------------------------------------- pointer

スレッドポインタは、Java VMの内部スレッド構造へのポインタです。ライブのJava VMまたはコアファイルをデバッグする場合を除いて、通常は問題ありません。

この最後の説明は、HotSpot VMを使用したJava SE 6のトラブルシューティングガイドからのものです。

スレッドダンプに関するいくつかのリンクを次に示します。


11

@James Drinkardの優れた答えに加えて:

基礎となる実装によっては、ネイティブメソッドでブロックされているスレッドのjava.lang.Thread.Stateがとして報告される場合があることに注意してくださいRUNNABLEA thread in the runnable state is executing in the Java virtual machine but it may be waiting for other resources from the operating system such as processor.

この説明には、ポーリングや読み取り操作などのOS呼び出しでブロックされることも含まれていることがわかります。おそらく、ネイティブメソッドの呼び出しがOSレベルでブロックされたことをJVMが認識できる保証がないためです。

私が見たJVMスレッドダンプの多くの議論は、この可能性を完全に無視するか、または影響を考慮せずにそれをざっと読み飛ばします-特に、監視ツールは、いくつかのそのようなスレッドが「実行中」であると混乱させて報告することがあり、さらにそれらはすべて100%で実行されています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.