介紹Java中的記憶體洩漏
Java語言的一個關鍵的優勢就是它的記憶體管理機制。你只管建立物件,Java的垃圾回收器幫你分配以及回收記憶體。然而,實際的情況並沒有那麼簡單,因為記憶體洩漏在Java應用程式中還是時有發生的。
下面就解釋下什麼是記憶體洩漏,它為什麼會發生,以及我們如何阻止它的發生。
1. 什麼是記憶體洩漏?
記憶體洩漏的定義:物件已經沒有被應用程式使用,但是垃圾回收器沒辦法移除它們,因為還在被引用著。
要想理解這個定義,我們需要先了解一下物件在記憶體中的狀態。下面的這張圖就解釋了什麼是無用物件以及什麼是未被引用物件。
Unused and Unreferenced
上面圖中可以看出,裡面有被引用物件和未被引用物件。未被引用物件會被垃圾回收器回收,而被引用的物件卻不會。未被引用的物件當然是不再被使用的物件,因為沒有物件再引用它。然而無用物件卻不全是未被引用物件。其中還有被引用的。就是這種情況導致了記憶體洩漏。
2. 為什麼會發生記憶體洩漏?
來先看看下面的例子,為什麼會發生記憶體洩漏。下面這個例子中,A物件引用B物件,A物件的生命週期(t1-t4)比B物件的生命週期(t2-t3)長的多。當B物件沒有被應用程式使用之後,A物件仍然在引用著B物件。這樣,垃圾回收器就沒辦法將B物件從記憶體中移除,從而導致記憶體問題,因為如果A引用更多這樣的物件,那將有更多的未被引用物件存在,並消耗記憶體空間。
B物件也可能會持有許多其他的物件,那這些物件同樣也不會被垃圾回收器回收。所有這些沒在使用的物件將持續的消耗之前分配的記憶體空間。
Object-Life-Time
3. 如何防止記憶體洩漏的發生?
下面是幾條容易上手的建議,來幫助你防止記憶體洩漏的發生。
- 特別注意一些像HashMap、ArrayList的集合物件,它們經常會引發記憶體洩漏。當它們被宣告為static時,它們的生命週期就會和應用程式一樣長。
- 特別注意事件監聽和回撥函式。當一個監聽器在使用的時候被註冊,但不再使用之後卻未被反註冊。
- “如果一個類自己管理記憶體,那開發人員就得小心記憶體洩漏問題了。” 通常一些成員變數引用其他物件,初始化的時候需要置空。
4. 一個小問題:為什麼JDK6中的substirng()方法容易導致記憶體洩漏?
要想解答上面的問題,你或許可以看看Substring() in JDK 6 and 7。
相關文章
- Java記憶體洩漏Java記憶體
- 翻譯 | 理解Java中的記憶體洩漏Java記憶體
- Java應用程式中的記憶體洩漏及記憶體管理Java記憶體
- vue使用中的記憶體洩漏Vue記憶體
- Android中的記憶體洩漏模式Android記憶體模式
- [譯] Swift 中的記憶體洩漏Swift記憶體
- Java記憶體洩漏解決之道Java記憶體
- java記憶體溢位和記憶體洩漏的區別Java記憶體溢位
- 分析記憶體洩漏和goroutine洩漏記憶體Go
- 記憶體洩漏的原因記憶體
- 納尼,Java 存在記憶體洩洩洩洩洩洩漏嗎?Java記憶體
- [Java基礎]記憶體洩漏和記憶體溢位Java記憶體溢位
- Java棧溢位|記憶體洩漏|記憶體溢位Java記憶體溢位
- 如何避免JavaScript中的記憶體洩漏?JavaScript記憶體
- jvm 記憶體洩漏JVM記憶體
- Android 記憶體洩漏Android記憶體
- js記憶體洩漏JS記憶體
- Android記憶體洩漏Android記憶體
- 一次 Java 記憶體洩漏的排查Java記憶體
- 小心遞迴中記憶體洩漏遞迴記憶體
- WebView引起的記憶體洩漏WebView記憶體
- [譯]理解閉包中的記憶體洩漏記憶體
- JavaScript中的垃圾回收和記憶體洩漏JavaScript記憶體
- 如何檢查Javascript中的記憶體洩漏JavaScript記憶體
- valgrind 記憶體洩漏分析記憶體
- 記憶體的分配與釋放,記憶體洩漏記憶體
- 【記憶體洩漏和記憶體溢位】JavaScript之深入淺出理解記憶體洩漏和記憶體溢位記憶體溢位JavaScript
- JVM——記憶體洩漏與記憶體溢位JVM記憶體溢位
- Android中常見的記憶體洩漏Android記憶體
- .NET 記憶體洩漏的爭議記憶體
- Swift的ARC和記憶體洩漏Swift記憶體
- 定位並修復 Go 中的記憶體洩漏Go記憶體
- 記憶體洩漏除錯工具記憶體除錯
- ThreadLocal真會記憶體洩漏?thread記憶體
- Perfdog 玩轉記憶體洩漏記憶體
- .Net程式記憶體洩漏解析記憶體
- iOS檢測記憶體洩漏iOS記憶體
- Android記憶體洩漏場景Android記憶體
- ThreadLocal記憶體洩漏問題thread記憶體