104

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 の後の角括弧内の数字は何ですか?

次に、スタック トレース自体の場合:

  • <.....> (a java.lang....) を待つとはどういう意味ですか? <..>の数字は何ですか?
  • ロックされた <.....> (a java.lang....)とはどういう意味ですか? 同じ質問、<..>の内容

ロックという言葉は何らかの待機状態に関連していると思っていましたが、間違っていました。実際、locked が 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 とは何ですか?

スレッド クラスの証拠がなく、スタック トレースが非常に短いのはなぜですか?

私のすべての質問に答えていただければ、とてもありがたいです。

ありがとう

4

2 に答える 2

118

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

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

IBM のサイトで、次のリンクを見つけました: How to interpret a thread dump . これをより詳細にカバーしています:

待機が何を意味するかを説明しています。ロックは、複数のエンティティが共有リソースにアクセスするのを防ぎます。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.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:118) 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 のトラブルシューティング ガイドからのものです。

スレッド ダンプに関するその他のリンクを次に示します。

于 2011-09-29T15:47:29.327 に答える
12

さらに@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% で実行されています。

于 2016-04-06T17:47:35.897 に答える