溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在JVM中使用JFR解決內存泄露

發(fā)布時間:2021-06-03 15:46:45 來源:億速云 閱讀:330 作者:Leah 欄目:開發(fā)技術

今天就跟大家聊聊有關怎么在JVM中使用JFR解決內存泄露,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據(jù)這篇文章可以有所收獲。

一個內存泄露的例子

我們舉一個內存泄露的例子,先定義一個大對象:

public class KeyObject {
    List<String> list = new ArrayList<>(200);
}

然后使用它:

public class TestMemoryLeak {

    public static HashSet<Object> hashSet= new HashSet();

    public static void main(String[] args) throws InterruptedException {
        boolean flag= true;
        while(flag){
            KeyObject keyObject= new KeyObject();
            hashSet.add(keyObject);
            keyObject=null;
            Thread.sleep(1);
        }
        System.out.println(hashSet.remove(new KeyObject()));
    }
}

在這個例子中,我們將new出來的KeyObject對象放進HashSet中。
然后將keyObject置為空。

但是因為類變量hashSet還保留著對keyObject的引用,所以keyObject對象并不會被回收。

注意,最后一行我們加了一個hashSet.remove的代碼,來使用類變量hashSet。
為什么要這樣做呢?這樣做是為了防止JIT對代碼進行優(yōu)化,從而影響我們對內存泄露的分析。

使用JFR和JMC來分析內存泄露

Flight Recorder(JFR)主要用來記錄JVM的事件,我們可以從這些事件中分析出內存泄露。

可以通過下面的指令來開啟JFR:

java -XX:StartFlightRecording

當然我們也可以使用java神器jcmd來開啟JFR:

jcmd pid JFR.dump filename=recording.jfr path-to-gc-roots=true

這里我們使用JMC來圖形化分析一下上面的例子。

怎么在JVM中使用JFR解決內存泄露

開啟JMC,找到我們的測試程序,打開飛行記錄器。

怎么在JVM中使用JFR解決內存泄露

可以看到我們的對象在飛行記錄器期間分配了4MB的內存,然后看到整體的內存使用量是穩(wěn)步上升的。

我們什么時候知道會有內存泄露呢?最簡單的肯定就是OutOfMemoryErrors,但是有些很隱蔽的內存泄露會導致內存使用緩步上漲,這時候就需要我們進行細致的分析。

通過分析,我們看到內存使用在穩(wěn)步上漲,這其實是很可疑的。

接下來我們通過JVM的OldObjectSample事件來分析一下。

OldObjectSample

OldObjectSample就是對生命周期比較長的對象進行取樣,我們可以通過研究這些對象,來檢查潛在的內存泄露。

怎么在JVM中使用JFR解決內存泄露

這里我們關注一下事件瀏覽器中的Old Object Sample事件,我們可以在左下方看到事件的詳情。

或者你可以使用jfr命令直接將感興趣的事件解析輸出:

jfr print --events OldObjectSample flight_recording_1401comflydeanTestMemoryLeak89268.jfr   > /tmp/jfrevent.log

我們看一個具體的輸出Sample:

jdk.OldObjectSample {

  startTime = 19:53:25.607

  allocationTime = 19:50:51.924

  objectAge = 2 m 34 s

  lastKnownHeapUsage = 3.5 MB

  object =  [

    java.lang.Object[200]

  ]

  arrayElements = 200

  root = N/A

  eventThread = "main" (javaThreadId = 1)

  stackTrace = [

    java.util.ArrayList.<init>(int) line: 156

    com.flydean.KeyObject.<init>() line: 11

    com.flydean.TestMemoryLeak.main(String[]) line: 17

  ]

}

看完上述內容,你們對怎么在JVM中使用JFR解決內存泄露有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI