介紹Java中的內(nèi)存泄漏
Java語言的一個(gè)關(guān)鍵的優(yōu)勢就是它的內(nèi)存管理機(jī)制。你只管創(chuàng)建對象,Java的垃圾回收器幫你分配以及回收內(nèi)存。然而,實(shí)際的情況并沒有那么簡單,因?yàn)閮?nèi)存泄漏在Java應(yīng)用程序中還是時(shí)有發(fā)生的。
下面就解釋下什么是內(nèi)存泄漏,它為什么會(huì)發(fā)生,以及我們?nèi)绾巫柚顾陌l(fā)生。
1. 什么是內(nèi)存泄漏?內(nèi)存泄漏的定義:對象已經(jīng)沒有被應(yīng)用程序使用,但是垃圾回收器沒辦法移除它們,因?yàn)檫€在被引用著。
要想理解這個(gè)定義,我們需要先了解一下對象在內(nèi)存中的狀態(tài)。下面的這張圖就解釋了什么是無用對象以及什么是未被引用對象。
Unused and Unreferenced
上面圖中可以看出,里面有被引用對象和未被引用對象。未被引用對象會(huì)被垃圾回收器回收,而被引用的對象卻不會(huì)。未被引用的對象當(dāng)然是不再被使用的對象,因?yàn)闆]有對象再引用它。然而無用對象卻不全是未被引用對象。其中還有被引用的。就是這種情況導(dǎo)致了內(nèi)存泄漏。
2. 為什么會(huì)發(fā)生內(nèi)存泄漏?來先看看下面的例子,為什么會(huì)發(fā)生內(nèi)存泄漏。下面這個(gè)例子中,A對象引用B對象,A對象的生命周期(t1-t4)比B對象的生命周期(t2-t3)長的多。當(dāng)B對象沒有被應(yīng)用程序使用之后,A對象仍然在引用著B對象。這樣,垃圾回收器就沒辦法將B對象從內(nèi)存中移除,從而導(dǎo)致內(nèi)存問題,因?yàn)槿绻鸄引用更多這樣的對象,那將有更多的未被引用對象存在,并消耗內(nèi)存空間。
B對象也可能會(huì)持有許多其他的對象,那這些對象同樣也不會(huì)被垃圾回收器回收。所有這些沒在使用的對象將持續(xù)的消耗之前分配的內(nèi)存空間。
Object-Life-Time
3. 如何防止內(nèi)存泄漏的發(fā)生?下面是幾條容易上手的建議,來幫助你防止內(nèi)存泄漏的發(fā)生。
特別注意一些像HashMap、ArrayList的集合對象,它們經(jīng)常會(huì)引發(fā)內(nèi)存泄漏。當(dāng)它們被聲明為static時(shí),它們的生命周期就會(huì)和應(yīng)用程序一樣長。特別注意事件監(jiān)聽和回調(diào)函數(shù)。當(dāng)一個(gè)監(jiān)聽器在使用的時(shí)候被注冊,但不再使用之后卻未被反注冊。“如果一個(gè)類自己管理內(nèi)存,那開發(fā)人員就得小心內(nèi)存泄漏問題了。” 通常一些成員變量引用其他對象,初始化的時(shí)候需要置空。 4. 一個(gè)小問題:為什么JDK6中的substirng()方法容易導(dǎo)致內(nèi)存泄漏?要想解答上面的問題,你或許可以看看Substring() in JDK 6 and 7。
外文鏈接:The Introduction of Java Memory Leaks
相關(guān)文章:
1. Intellij IDEA連接Navicat數(shù)據(jù)庫的方法2. 如何通過axios發(fā)起Ajax請求(最新推薦)3. JSP之表單提交get和post的區(qū)別詳解及實(shí)例4. 使用Docker的NFS-Ganesha鏡像搭建nfs服務(wù)器的詳細(xì)過程5. python 指定源路徑來解決import問題的操作6. Django日志及中間件模塊應(yīng)用案例7. Spring Module 0.3 版本發(fā)布8. SpringBoot使用Thymeleaf模板引擎訪問靜態(tài)html的過程9. 詳解Struts2中對未登錄jsp頁面實(shí)現(xiàn)攔截功能10. jsp網(wǎng)頁實(shí)現(xiàn)貪吃蛇小游戲
