Java內(nèi)存泄露學(xué)習(xí) java.lang.OutOfMemoryError: GC overhead limit exceeded

1、我們手寫一個內(nèi)存泄露的案例,來體驗一下

用我們比較熟悉的Spring來實現(xiàn),定義一個Bean,實現(xiàn)InitializingBean接口,在afterPropertiesSet方法中定時每隔1秒鐘生成一批對象,加入到list中

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * Created by martin.xie on 2020/4/28.
 */
@Component
public class MemLeaker implements InitializingBean {
    private List<Object> objs = new LinkedList<>();
    ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

    @Override
    public void afterPropertiesSet() throws Exception {
        service.scheduleAtFixedRate(() -> {
            System.out.println("start add obj...");
            for (int i = 0; i < 50000; i++) {
                objs.add(new Object());
            }
        }, 1000, 1000, TimeUnit.MILLISECONDS);
    }
}

2、啟動容器,使用如下啟動參數(shù)

-XX:+PrintGCDetails
-XX:MetaspaceSize=128m
-XX:MaxMetaspaceSize=128m
-XX:+PrintGCDateStamps
-XX:+PrintGCApplicationStoppedTime
-Xloggc:D:/loggc/gc.log
-XX:-OmitStackTraceInFastThrow
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=D:/loggc
-XX:+PrintCommandLineFlags
-XX:+PrintFlagsFinal
-Xms256m -Xmx256m -Xmn64m

3、過2分鐘后查看控制臺,出現(xiàn)GC overhead limit exceeded,這個提示大多數(shù)是意味著系統(tǒng)內(nèi)存泄露導(dǎo)致最后溢出了。
因為spring容器中的bean MemLeaker 只要不銷毀就會一直存在,bean的objs屬性中的對象也沒辦法被回收。不斷地增加對象到list中就會導(dǎo)致內(nèi)存占用持續(xù)增加,GC不停地進行回收卻沒有效果

java.lang.OutOfMemoryError: GC overhead limit exceeded
Dumping heap to D:/loggc\java_pid9380.hprof ...
Heap dump file created [433345651 bytes in 2.296 secs]
java.lang.OutOfMemoryError: GC overhead limit exceeded
Exception in thread "ContainerBackgroundProcessor[StandardEngine[Catalina]]" java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: GC overhead limit exceeded
java.lang.OutOfMemoryError: GC overhead limit exceeded
Exception in thread "Timer-0" java.lang.OutOfMemoryError: GC overhead limit exceeded

4、從gc log中也可以發(fā)現(xiàn)GC的結(jié)果,[ParOldGen: 196139K->196138K(196608K)] 老年代回收前后所占用的內(nèi)存非常接近,而且占用量接近196608總的內(nèi)存數(shù)

2020-04-29T18:05:17.436+0800: 301.896: Total time for which application threads were stopped: 0.4551662 seconds, Stopping threads took: 0.0000148 seconds
2020-04-29T18:05:17.436+0800: 301.896: [Full GC (Ergonomics) [PSYoungGen: 48639K->48639K(56832K)] [ParOldGen: 196140K->196137K(196608K)] 244780K->244777K(253440K), [Metaspace: 60852K->60852K(1103872K)], 0.4698420 secs] [Times: user=1.12 sys=0.00, real=0.47 secs] 
2020-04-29T18:05:17.906+0800: 302.366: Total time for which application threads were stopped: 0.4701188 seconds, Stopping threads took: 0.0000298 seconds
2020-04-29T18:05:17.907+0800: 302.367: [Full GC (Ergonomics) [PSYoungGen: 48639K->48639K(56832K)] [ParOldGen: 196137K->196136K(196608K)] 244777K->244776K(253440K), [Metaspace: 60852K->60852K(1103872K)], 0.7593071 secs] [Times: user=1.58 sys=0.00, real=0.76 secs] 
2020-04-29T18:05:18.666+0800: 303.126: Total time for which application threads were stopped: 0.7595541 seconds, Stopping threads took: 0.0000183 seconds
2020-04-29T18:05:18.667+0800: 303.127: [Full GC (Ergonomics) [PSYoungGen: 48640K->48639K(56832K)] [ParOldGen: 196139K->196138K(196608K)] 244779K->244778K(253440K), [Metaspace: 60852K->60852K(1103872K)], 0.7987929 secs] [Times: user=1.50 sys=0.00, real=0.80 secs] 
2020-04-29T18:05:19.466+0800: 303.926: Total time for which application threads were stopped: 0.7990989 seconds, Stopping threads took: 0.0000302 seconds

5、分析heapdump文件, 從D:\loggc\java_pid9380.hprof找到剛生成的dump文件,用MAT工具打開
Overview里面看到內(nèi)存占用情況的餅圖,以及Histogram、 Dominator Tree、 Leak Suspects 各種報告的入口。


image.png

其中Histogram就是各種類實例對象的個數(shù)以及占用的內(nèi)存大小,打開可以發(fā)現(xiàn)排在第一的就是java.util.LinkedList$Node。


image.png

然后MAT工具自帶內(nèi)存泄露的分析,打開Leak Suspects就可以看到problem,里面提到MemLeaker這個實例中的LinkedList這個實例累計占用了72.49%的內(nèi)存。點擊Details可以查看詳情

image.png
image.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容