jps、jmap、jstack已經Out了,使用jcmd進行JVM效能和記憶體跟蹤微調 -DZone Java

banq發表於2020-09-03

當您的應用程式在真實環境中執行時,您開始遇到在本地或開發環境中未發現的問題。
您如何與應用程式進行互動以查詢應用程式的執行方式並找到問題的根源?JVM的優勢之一是可用於診斷的工具數量眾多。
如果監視和應用程式日誌提供的資訊不夠,我們必須進入伺服器並使用這種型別的實用程式。
其中一些被視為實驗性的工具(jps,jmap,jstack ...)正在收斂到jcmd命令中
jcmd是隨JDK一起分發的只有幾千位元組的實用程式。它只是JVM的前端/客戶端,所有邏輯都駐留在JVM中。如果您使用不包含jcmd可執行檔案的發行版或docker映像,並將其新增到路徑中,則它將不起作用。您需要使用jcmd模組生成JVM 。
這裡可以學習如何使用jcmd診斷問題:獲取堆疊跟蹤,記憶體直方圖,堆轉儲,GC日誌等。
 

獲取pid
每個程式都有一個關聯的程式ID,稱為pid。要獲得與我們的應用程式關聯的pid,可以使用jcmd本身,它將列出所有適用的Java程式。

$JAVA_HOME/bin/jcmd
12385 org.apache.catalina.startup.Bootstrap start
3019 sun.tools.jcmd.JCmd


我們的應用是tomcat的12385
 

JCMD命令列表
鍵入:

jcmd 12385 help

  • 獲得虛擬機器版本:

jcmd 12385 VM.version
12385:
Java HotSpot(TM) Server VM version 25.171-b11
JDK 8.0_171

  • 虛擬機器JVM引數

jcmd 12385 VM.flags
12385:
-XX:CICompilerCount=2 -XX:CMSInitiatingOccupancyFraction=90 -XX:+CMSParallelRemarkEnabled -XX:+CMSScavengeBeforeRemark -XX:+DisableExplicitGC -XX:InitialHeapSize=1572864000 -XX:+ManagementServer -XX:MaxGCPauseMillis=50 -XX:MaxHeapSize=1572864000 -XX:MaxNewSize=134217728 -XX:MaxTenuringThreshold=6 -XX:MinHeapDeltaBytes=131072 -XX:NewSize=134217728 -XX:OldPLABSize=16 -XX:OldSize=1438646272 -XX:+ScavengeBeforeFullGC -XX:+UseAdaptiveGCBoundary -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseConcMarkSweepGC -XX:+UseParNewGC 


其他命令,例如VM.system_properties,VM.command_line,VM.uptime,VM.dynlibs,還提供了有關所使用的各種其他屬性的其他基本和有用的詳細資訊。
  • 執行緒列印

該命令用於獲取執行緒轉儲,即它將列印當前正在執行的所有執行緒的堆疊跟蹤。

jcmd 12385 Thread.print

  • GC.class_histogram

該命令將提供有關堆使用情況的重要資訊,並列出所有類(外部類或特定於應用程式的類)以及許多例項,並按堆使用情況對它們的堆使用進行排序。由於此列表很長,因此可以使用grep命令來查詢其已知的類以驗證詳細資訊,或者可以將此命令的輸出路由到檔案輸出。以下是JiveJdon執行情況:

num     instances         bytes  class name
----------------------------------------------
   1:        851817      171944304  [C
   2:          5157       33565504  [B
   3:         81230       17192520  [Ljava.lang.Object;
   4:        849365       13589840  java.lang.String
   5:        265701        8502432  java.lang.ref.Finalizer
   6:        504856        8077696  java.lang.Long
   7:        222058        5329392  java.util.ArrayList
   8:         58818        5175984  com.jdon.jivejdon.domain.model.ForumMessageReply
   9:        114716        4588640  com.google.common.cache.LocalCache$StrongAccessEntry
  10:         79245        1901880  com.jdon.jivejdon.domain.model.message.MessageVO
  11:        114720        1835520  com.google.common.cache.LocalCache$StrongValueReference
  12:        114716        1835456  com.jdon.cache.CacheableWrapper
  13:         20427        1634160  com.jdon.jivejdon.domain.model.ForumMessage

  • GC.heap_dump

如果要立即獲取jvm堆轉儲,則可以執行此命令。

jcmp 12385 GC.heap_dump 檔名

  • JFR命令選項

如果要分析其應用程式的效能問題,那麼JFR(即Java Flight Recorder)是一種提供資訊的實用工具。儘管JFR是一項商業功能,但人們可以在其本地計算機上免費使用它。
jcmd命令可以提供相關的JFR檔案以進行動態分析。預設情況下,JFR功能處於禁用狀態,要啟用這些功能,需要使用JFR.start
啟用JFR功能後,開始JFR錄製。就我而言,我要求在延遲10秒後記錄30秒。可以根據用途進行配置。也可以使用  JFR.check 命令檢查記錄的狀態。
  • VM.native_memory(本機記憶體跟蹤)

這是最好的命令之一,可以提供有關堆和非堆 記憶體的許多有用的詳細資訊。這可用於調整記憶體使用情況並檢測任何記憶體洩漏。 
眾所周知,JVM記憶體的使用取決於許多記憶體區域,大致分為堆和非堆記憶體。要獲取完整的JVM記憶體使用情況的詳細資訊,請使用此實用程式。如果要建立分散式應用程式,則這對於定義應用程式容器的大小很有用,如果正確調整,則可以節省成本。
要使用此功能,我必須使用其他引數重新啟動應用程式,即-XX:NativeMemoryTracking = summary   或  -XX:NativeMemoryTracking = detail。
結果解釋:
Java Heap記憶體外,Thread項指定執行緒正在使用的記憶體,Class項還指定捕獲的用於儲存類後設資料的記憶體,Code項提供用於儲存JIT生成的程式碼的記憶體,Compiler項本身具有一定的空間使用率,類似GC佔用空間。所有這些都屬於本機記憶體使用情況。reserved項可以粗略估計您的應用程式所需的記憶體,但是各種VM引數仍然可以控制事情,這主要是預設記憶體使用情況。

例如:

Java Heap (reserved=524288KB, committed=524288KB)
                (mmap: reserved=524288KB, committed=524288KB) 


我們預定reserved了堆記憶體即Xms = 512m,相當於524288KB,因此JVM確認的記憶體與Xms相同。同樣,Xmx對映到預定的記憶體。
  • 記憶體洩漏分析

VM.native_memory命令提供當前記憶體使用情況的快照。要分析記憶體洩漏,應在使用命令啟動應用程式後將記憶體統計資訊作為基準:

jcmd #pid VM.native_memory baseline


然後,可以使用summary.diff觀察更改,確切地使用記憶體。隨著GC的執行,您會發現記憶體增加和減少。但是,如果僅增加記憶體使用量,則可能是記憶體洩漏問題。確定洩漏區域,例如堆,執行緒,程式碼,類等。如果您的應用程式需要更多記憶體,請相應地調整相應的VM引數。
如果記憶體洩漏在堆中,請進行堆轉儲(如前所述),或者如果執行緒數在增加,請使用執行緒池。如果任何執行緒導致OOM,可以調整Xss。 

thread (reserved=11895KB +529KB, committed=11895KB +529KB)
                (thread #20 +2)
                (stack: reserved=11812KB +520KB, committed=11812KB +520KB)
                (malloc=61KB +7KB #101 +10)
                (arena=22KB +2 #35 +4)


“ stack ”顯示執行緒堆疊記憶體,這可能與執行應用程式時使用Xss配置的內容不匹配。由於某些jvm系統執行緒會根據使用情況分配堆疊記憶體,因此使用者無法使用Xss覆蓋堆疊記憶體。 
我們將執行緒堆疊大小指定為Xss = 256k,這裡共有18 + 2 = 20個執行緒。這兩個額外的執行緒是處理請求的特定於應用程式的執行緒,因此2 *(Xss = 256k)〜520k。

相關文章