總覽
術語“內存泄漏”在Java中的使用方式不同于在其他語言中使用的方式。 通用術語中的“內存泄漏”是什么意思,在Java中如何使用?
維基百科的定義
當計算機程序消耗內存但無法將其釋放回操作系統時,就會發生計算機科學中的內存泄漏(在此情況下為泄漏)。
JVM在啟動時將堆保留為虛擬內存,并且直到退出后才將其歸還。 該虛擬內存在使用時會變成主內存。 這就是為什么JVM的虛擬大小和駐留大小可能非常不同,并且駐留內存可以在不更改虛擬內存的情況下增長的原因。
在面向對象的編程中,當對象存儲在內存中但無法被運行的代碼訪問時,就會發生內存泄漏。
GC總是可以找到堆上的每個對象,甚至是應用程序無法訪問的對象。 這樣,就沒有運行代碼無法達到的對象。
但是,許多人將內存使用中的任何不必要的增加都稱為內存泄漏,盡管從技術角度來看這并不是嚴格準確的。
在Java中,沒有完整的GC就無法確定所需的內存量。 看到Java應用程序鋸齒狀的“已用”內存是正常的。 在每個GC之后返回相同的內存量表示所需的內存沒有增加。
內存泄漏會通過減少可用內存量來降低計算機的性能。 最終,在最壞的情況下,可能會分配過多的可用內存,并且系統或設備的全部或部分停止正常工作,應用程序出現故障,或者系統由于崩潰而無法正常運行。
這就是該術語在Java中的用法。 結論是可用內存減少了,這是內存泄漏。
但這真的是內存泄漏嗎?
Java中的“內存泄漏”示例
最近,在StackOverflow上提出了兩個問題,這些問題說明了Java中“內存泄漏”的含義的各種觀點。
Go是否會像Java一樣受到微妙的內存泄漏?
在Java中創建內存泄漏
在第一篇文章中,有一種觀點表示“內存泄漏”是指應用程序持有對不再需要的對象的引用。 另一種觀點認為,JVM本身沒有內存泄漏。
在第二篇文章中,有許多示例說明了如何使用JVM來隱藏內存使用情況或消耗內存的操作。 示例包括File.deleteOnExit(),創建大的靜態字段,廢棄的套接字,文件句柄,線程,不需要的JDBC連接。
退出時File.deleteOnExit必須使用一些內存才能執行其任務。 這不是我的選擇的泄漏,因為它沒有保留不需要的內存。
具有不需要的靜態字段和線程會浪費內存,這是JVM無法糾正的錯誤。
但是,創建JVM處理的套接字,文件句柄和JDBC連接。 調用finalize()方法時,將清除這些資源。
結論
在Java中,將保留且不再需要的對象稱為“內存泄漏”是有意義的。
Java語言中沒有什么容易出現此問題的,并且JRE庫可以保護自己免受應用程序代碼中的錯誤的侵害。
您的應用程序仍然可能存在內存泄漏,您需要對何時仍需要資源(特別是線程)做出明智的選擇,如果您堅持太長時間,則可能意味著您存在“內存泄漏”。
參考: Vanilla Java博客上來自我們的JCG合作伙伴
Java和內存泄漏 。- Java中的低GC:使用原語而不是包裝器
- Erlang與Java內存架構
- JVM如何處理鎖
- JVM選項:-client vs -server
翻譯自: https://www.javacodegeeks.com/2011/07/java-and-memory-leaks.html