1. 程式人生 > 其它 >Java InputStream未呼叫close方法進行資源關閉造成直接記憶體洩漏

Java InputStream未呼叫close方法進行資源關閉造成直接記憶體洩漏

技術標籤:問題排查Java

今天做一個測試,測試InputStream未關閉資源是否會造成記憶體洩漏

一 測試程式準備

未關閉InputStream的Java程式【UrlStreamNoClose.java】:

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

public class UrlStreamNoClose {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10000000; i++) {
            System.out.println("載入次數:" + i);
            InputStream is = new URL("jar:file:/Users/bingsanfang/Desktop/jrt-fs.jar!/META-INF/MANIFEST.MF").openStream();
        }
    }
}

關閉InputStream的程式【UrlStreamClose.java】:

mport java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;

public class UrlStreamClose {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 10000000; i++) {
            System.out.println("載入次數:" + i);
            try(InputStream is = new URL("jar:file:/Users/bingsanlang/Desktop/jrt-fs.jar!/META-INF/MANIFEST.MF").openStream()){
                System.out.println("enter" + i);
            }
        }
    }
}

對以上兩個程式分別執行打包程式打成可執行jar包,以第一個程式為例,執行打包的流程如下:

javac UrlStreamNoClose.java
jar -cvf UrlStreamNoClose.jar UrlStreamNoClose.class

打包完成後,需要修改Meta資訊,否則會報錯:無執行清單

vim UrlStreamNoClose.jar

選擇META-INF/MANIFEST.MF進行修改,新增第三行的內容,注意:後面有個空格。
在這裡插入圖片描述
新增完成後就可以執行了。

二、測試

2.1 記憶體洩漏測試:未關閉close

執行 如下命令,觀察這個程序使用的記憶體大小:

java -jar UrlStreamNoClose.jar

可以看到一直輸出,通過監控可以看到記憶體使用一直上漲,上漲到5G了:
在這裡插入圖片描述
這時候可以執行jps檢視程序ip,然後 執行kill殺掉程序:

192:/ bingsanlang$ jps
10933 Jps
10908 jar
192:/ bingsanlang$ kill -9 10908

2.2 關閉close,未產生記憶體洩漏

執行 如下命令,觀察這個程序使用的記憶體大小:

java -jar UrlStreamClose.jar

可以看到一直輸出,通過監控可以看到記憶體使用一直平穩,只有800多M:
在這裡插入圖片描述

三、結論

使用URL.openStream 應主動關閉,否則容易造成記憶體洩漏,try可以實現關閉資源的能力,關閉的程式碼執行路徑如下:

在這裡插入圖片描述