簡體   English   中英

如何分析java線程轉儲?

[英]How to analyze a java thread dump?

我試圖更多地了解java,尤其是關於內存管理和線程。 出於這個原因,我最近發現有興趣查看線程轉儲。

以下是使用VisualVM(一種用於java的內置工具)從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 ....)同樣的問題, <...>中的內容

我認為鎖定這個詞在某種程度上與等待條件有關,但是,我錯了。 事實上,我想知道為什么鎖定重復三次,但線程處於可運行狀態,如同一個轉儲中所示:

"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?

為什么堆棧跟蹤如此短暫而沒有任何線程類的證據?

如果你能回答我的所有問題,我將非常感激。

謝謝

TID是thead id,NID是:本機線程ID。 此ID高度依賴於平台。 它是jstack線程轉儲中的NID。 在Windows上,它只是進程中的操作系統級線程ID。 在Linux和Solaris上,它是線程的PID(反過來又是一個輕量級的過程)。 在Mac OS X上,它被稱為本機pthread_t值。

轉到此鏈接: Java級別的線程ID :有關這兩個術語的定義和進一步說明。

在IBM的網站上,我找到了這個鏈接: 如何解釋線程轉儲 更詳細地介紹了這一點:

它解釋了等待意味着什么:鎖定阻止多個實體訪問共享資源。 Java™中的每個對象都有一個關聯的鎖(通過使用同步塊或方法獲得)。 對於JVM,線程競爭JVM中的各種資源並鎖定Java對象。

然后,它將監視器描述為一種特殊的鎖定機制,在JVM中使用它以允許線程之間的靈活同步。 出於本節的目的,請交替閱讀術語監視器和鎖定。

然后它進一步:

為避免在每個對象上都有監視器,JVM通常使用類或方法塊中的標志來指示該項是否已鎖定。 大多數情況下,一段代碼會在沒有爭用的情況下傳輸一些鎖定的部分。 因此,監護人標志足以保護這段代碼。 這稱為平板顯示器。 但是,如果另一個線程想要訪問某些已鎖定的代碼,則會發生真正的爭用。 JVM現在必須創建(或膨脹)監視器對象以保存第二個線程,並安排信號機制來協調對代碼段的訪問。 此監視器現在稱為充氣監視器。

以下是對線程轉儲中的內容進行更深入的解釋。 Java線程由操作系統的本機線程實現。 每個線程用粗體表示,例如:

“Thread-1”(TID:0x9017A0,sys_thread_t:0x23EAC8,狀態:R,本機ID:0x6E4)prio = 5

*以下6個項目解釋了這一點,因為我從示例中匹配它們,括號[]中的值:

  1. name [ Thread-1 ],
  2. 標識符[ 0x9017A0 ],
  3. JVM數據結構地址[ 0x23EAC8 ],
  4. 現狀[ R ],
  5. 本機線程標識符[ 0x6E4 ],
  6. 和優先[ 5 ]。

“等待”似乎是與jvm本身相關聯的守護程序線程,而不是應用程序線程perse。 當你得到一個“在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故障排除指南

以下是有關線程轉儲的更多鏈接:

繼@James Drinkard的優秀答案:

請注意,根據底層實現,在本機方法中阻塞的線程的java.lang.Thread.State可能會報告為RUNNABLE ,其中A 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調用中被阻止 - 可能是因為無法保證JVM可以知道本機方法調用何時在OS級別被阻止。

我所看到的許多關於JVM線程轉儲的討論要么完全忽略了這種可能性,要么在沒有考慮其影響的情況下輕率地略過它 - 尤其是監控工具可能會混淆地報告幾個這樣的線程正在“運行”,而且他們都在100%運行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM