[轉帖]如何通過Native Memory Tracking追蹤JVM的內部內存使用?

https://zhuanlan.zhihu.com/p/368599144#

 

導讀:Java8給 HotSpot VM引入了Native Memory Tracking (便於閱讀我統一簡稱爲NMT)特性,可以用於追蹤JVM的內部內存使用,並可以通過jcmd命令來訪問。不過要注意的是NMT是通過在JVM代碼中添加跟蹤點的方式實現內存跟蹤的,因此NMT不能跟蹤第三方Native庫的內存使用。

怎樣開啓NMT?

使用-XX:NativeMemoryTracking=summary可以用於開啓NMT,其中該值默認爲off,可以設置爲summary或者detail來開啓;開啓的話,大概會增加5%-10%的性能消耗

-XX:NativeMemoryTracking=[off | summary | detail]

參數說明

注意,根據Java官方文檔,開啓NMT會有5%-10%的性能損耗;

如果想JVM退出時打印退出時的內存使用情況,可以通過如下配置項:

-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics

怎樣訪問NMT數據?

我們可以通過通過jcmd查看NMT報告以及查看對比情況。

使用jcmd pid VM.native_memory可以查看,後面可以加summary或者detail,如果是開啓summary的,就只能使用summary;其中scale參數可以指定展示的單位,可以爲KB或者MB或者GB
jcmd <pid> VM.native_memory [summary | detail | baseline | summary.diff | detail.diff | shutdown] [scale= KB | MB | GB]

參數說明

爲了查看詳情我本地也開啓了jvisualvm(這裏就對於jvisualvm不做過多贅述,下幾期會詳細介紹),線程ID可以直接看到。當然自己可以查詢對應的應用線程

使用jcmd查看NMT報告

  • 可以看到整個memory主要包含了Java Heap、Class、Thread、Code、GC、Compiler、Internal、Other、Symbol、Native Memory Tracking、Arena Chunk這幾部分;其中reserved表示應用可用的內存大小,committed表示應用正在使用的內存大小
  • Java Heap部分表示heap內存目前佔用了4246MB;Class部分表示已經加載的classes個數爲1131,Thread部分表示目前有169個線程,佔用了169MB;Code部分表示JIT生成的或者緩存的instructions佔用了251MB;GC部分表示目前已經佔用了162MB的內存空間用於幫助GC;Code部分表示compiler生成code的時候佔用了26MB;Internal部分表示命令行解析、JVMTI等佔用了5MB;Other部分表示尚未歸類的佔用了2MB;Symbol部分表示諸如string table及constant pool等symbol佔用了10MB;Native Memory Tracking部分表示該功能自身佔用了6MB。
  • 一個arena表示使用malloc分配的一個memory chunk,這些chunks可以被其他subsystems做爲臨時內存使用,比如pre-thread的內存分配,它的內存釋放是成bulk的

參數說明

  • Java Heap: 堆內存,即-Xmx限制的最大堆大小的內存。
  • Class:加載的類與方法信息,其實就是 metaspace,包含兩部分:一是 metadata,被-XX:MaxMetaspaceSize限制最大大小,另外是 class space,被-XX:CompressedClassSpaceSize限制最大大小
  • Thread:線程與線程棧佔用內存,每個線程棧佔用大小受-Xss限制,但是總大小沒有限制。
  • Code:JIT 即時編譯後(C1 C2 編譯器優化)的代碼佔用內存,受-XX:ReservedCodeCacheSize限制
  • GC:垃圾回收佔用內存,例如垃圾回收需要的 CardTable,標記數,區域劃分記錄,還有標記 GC Root 等等,都需要內存。這個不受限制,一般不會很大的。
  • Compiler:C1 C2 編譯器本身的代碼和標記佔用的內存,這個不受限制,一般不會很大的
  • Internal:命令行解析,JVMTI 使用的內存,這個不受限制,一般不會很大的
  • Symbol: 常量池佔用的大小,字符串常量池受-XX:StringTableSize個數限制,總內存大小不受限制
  • Native Memory Tracking:內存採集本身佔用的內存大小,如果沒有打開採集(那就看不到這個了,哈哈),就不會佔用,這個不受限制,一般不會很大的
  • Arena Chunk:所有通過 arena 方式分配的內存,這個不受限制,一般不會很大的
  • Tracing:所有采集佔用的內存,如果開啓了 JFR 則主要是 JFR 佔用的內存。這個不受限制,一般不會很大的
  • Logging,Arguments,Module,Synchronizer,Safepoint,Other,這些一般我們不會關心。

總結

工欲善其事必先利其器,NMT用於追蹤JVM的內部內存使用還是很高效的。簡單梳理下有一下幾點

  • Java8給HotSpot VM引入了Native Memory Tracking (NMT)特性,可以用於追蹤JVM的內部內存使用
  • 使用-XX:NativeMemoryTracking=summary可以用於開啓NMT,其中該值默認爲off,可以設置summary、detail來開啓;開啓的話,大概會增加5%-10%的性能消耗;使用-XX:+UnlockDiagnosticVMOptions -XX:+PrintNMTStatistics可以在jvm shutdown的時候輸出整體的native memory統計;其他的可以使用jcmd pid VM.native_memory相關命令進行查看、diff、shutdown等
  • 整個memory主要包含了Java Heap、Class、Thread、Code、GC、Compiler、Internal、Other、Symbol、Native Memory Tracking、Arena Chunk這幾部分;其中reserved表示應用可用的內存大小,committed表示應用正在使用的內存大小
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章