1. 程式人生 > 其它 >JVM記憶體堆疊分析

JVM記憶體堆疊分析

一、JVM執行緒堆疊資料分析

  JVM 內部執行緒主要分為以下幾種:

    VM 執行緒:單例的 VMThread 物件,負責執行 VM 操作;

    定時任務執行緒:單例的 WatcherThread 物件, 模擬在 VM 中執行定時操作的計時器中斷;

    GC 執行緒:垃圾收集器中,用於支援並行和併發垃圾回收的執行緒;

    編譯器執行緒: 將位元組碼編譯為本地機器程式碼;

    訊號分發執行緒:等待程序指示的訊號,並將其分配給Java 級別的訊號處理方法。

  GC進行垃圾回收時,會STW,那麼GC是如何讓所有的使用者執行緒都停止呢?其使用的是安全點,實現原理如下:

    1、方法程式碼中被植入的安全點檢測入口;

    2. 執行緒處於安全點狀態:執行緒暫停執行,這個時候執行緒棧不再發生改變;

    3. JVM 的安全點狀態:所有執行緒都處於安全點狀態。

  JVM 支援多種方式來進行執行緒轉儲:

    1. JDK 工具, 包括: jstack 工具, jcmd 工具,jconsole,jvisualvm, Java Mission Control 等;

    2. Shell 命令或者系統控制檯,比如 Linux 的 kill -3,Windows 的 Ctrl + Break 等;

    3. JMX 技術, 主要是使用 ThreadMxBean。

                

  fastthread 執行緒分析:(https://fastthread.io/)

        

二、記憶體分析與相關工具

  1、OutOfMemoryError: Java heap space

  建立新的物件時,堆記憶體中的空間不足以存放新建立的物件產生的原因。其實清楚了原因,問題就很容易解決了:只要增加堆記憶體的大小,程式就能正常執行。另外還有一些情況是由程式碼問題導致的:

    超出預期的訪問量/資料量:應用系統設計時,一般是有 “容量” 定義的,部署這麼多機器,用來處理一定流量的資料/業務。 如果訪問量突然飆升,超過預期的閾值,類似於時間座標系中針尖形狀的圖譜。那麼在峰值所在的時間段,程式很可能就會卡死、並觸發 ava.lang.OutOfMemoryError: Java heap space 錯誤。

    記憶體洩露(Memory leak):這也是一種經常出現的情形。由於程式碼中的某些隱蔽錯誤,導致系統佔用的記憶體越來越多。如果某個方法/某段程式碼存在記憶體洩漏,每執行一次,就會(有更多的垃圾物件)佔用更多的記憶體。隨著執行時間的推移,洩漏的物件耗光了堆中的所有記憶體,那麼 java.lang.OutOfMemoryError: Javaheap space 錯誤就爆發了。

  2、OutOfMemoryError: PermGen space/OutOfMemoryError: Metaspace

    java.lang.OutOfMemoryError: PermGen space 的主要原因,是載入到記憶體中的類數量太多或體積太大,超過了 PermGen 區的大小。

    解決辦法:增大 PermGen/Metaspace

      -XX:MaxPermSize=512m

      -XX:MaxMetaspaceSize=512m

    高版本 JVM 也可以:

      -XX:+CMSClassUnloadingEnabled

  3、OutOfMemoryError: Unable to create new native thread

    java.lang.OutOfMemoryError: Unable to create new native thread 錯誤是程式建立的執行緒數量已達到上限值的異常資訊。

    解決思路:

      1. 調整系統引數 ulimit -a,echo 120000 > /proc/sys/kernel/threads-max

      2. 降低 xss (為jvm啟動的每個執行緒分配的記憶體大小)等引數

      3. 調整程式碼,改變執行緒建立和使用方式

三、記憶體分析工具

  1、Eclipse MAT:https://www.cnblogs.com/loong-hon/p/10475143.html

   2、jhat:堆轉快照分析工具

  jhat和jmap是對著使用的,jhat用以分析jmap生成的堆轉快照檔案,但是一般不這麼用,一般會使用視覺化工具檢視。

  使用jhat+快照檔案命令後,出現already後即可使用

      

   從上圖可以看到埠號為7000,在瀏覽器訪問local host:7000

      

   可以看到分析結果是以包為單位進行分組顯示的,分析記憶體洩漏問題是要會用到其中的Heap Histogram與OQL頁籤的功能,Heap Histogram可以找到記憶體中總容量最大的物件,OQL是標準的物件查詢語言,使用類似SQL的語法進行查詢。