Java InputStream未呼叫close方法進行資源關閉造成直接記憶體洩漏
阿新 • • 發佈:2021-01-19
今天做一個測試,測試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可以實現關閉資源的能力,關閉的程式碼執行路徑如下: