獲取JVM轉儲文件的Java工具類

  • 2019 年 12 月 17 日
  • 筆記

在上期文章如何獲取JVM堆轉儲文件中,介紹了幾種方法獲取JVM的轉儲文件,其中編程方法是裏面唯一一個從JVM內部獲取的方法。這裡就不演示了其他方法獲取正在運行的應用程序的堆轉儲,重點放在了使用編程來獲取轉儲文件的方法,並演示了如何使用jhat工具瀏覽/分析生成的二進制堆轉儲。

你可能想在各個時間點從應用程序中轉儲多個堆快照,然後使用jhat離線分析這些快照。如何以編程方式從應用程序中轉儲堆?下面給出了一個例子。您可以從應用程序中轉儲堆,但必須進行一些編程,如下所示:

package com.fun.utils;    import com.fun.frame.SourceCode;  import com.sun.management.HotSpotDiagnosticMXBean;  import org.slf4j.Logger;    import javax.management.MBeanServer;  import java.lang.management.ManagementFactory;    public class HeapDumper extends SourceCode {        private static Logger logger = getLogger();        /**       * 這是HotSpot Diagnostic MBean的名稱       */      private static final String HOTSPOT_BEAN_NAME = "com.sun.management:type=HotSpotDiagnostic";        /**       * 用於存儲熱點診斷MBean的字段       */      private static volatile HotSpotDiagnosticMXBean hotspotMBean;        /**       * 下載內存轉儲文件       *       * @param fileName 文件名,例如:heap.bin,不兼容路徑,會在當前目錄下生成       * @param live       */      static void dumpHeap(String fileName, boolean live) {          initHotspotMBean();          try {              hotspotMBean.dumpHeap(fileName, live);          } catch (Exception e) {              logger.error("生成內存轉儲文件失敗!", e);          }      }        /**       * 初始化熱點診斷MBean       */      private static void initHotspotMBean() {          if (hotspotMBean == null) {              synchronized (HeapDumper.class) {                  if (hotspotMBean == null) {                      try {                          MBeanServer server = ManagementFactory.getPlatformMBeanServer();                          hotspotMBean = ManagementFactory.newPlatformMXBeanProxy(server, HOTSPOT_BEAN_NAME, HotSpotDiagnosticMXBean.class);                      } catch (Exception e) {                          logger.error("初始化mbean失敗!", e);                      }                  }              }          }      }      }  
  • 重要說明:雖然可以從應用程序中轉儲多個堆快照,但不能將多個轉儲中的對象相關聯。jmap工具使用對象地址作為對象標識符-在垃圾回收之間有所不同[回想一下GC可能會移動更改對象地址的對象]。但是,您可以通過匯總統計數據(例如直方圖等)進行關聯。

下面將生產好的heap.bin文件拉回到本地或者在服務端用jhat -port 8888 heap.bin工具進行處理,然後訪問:http://localhost:8888即可查看當時JVM堆內存的使用情況。如圖: