淺析Java中的內(nèi)存泄漏
ava最明顯的一個(gè)優(yōu)勢(shì)就是它的內(nèi)存管理機(jī)制。你只需簡(jiǎn)單創(chuàng)建對(duì)象,java的垃圾回收機(jī)制負(fù)責(zé)分配和釋放內(nèi)存。然而情況并不像想像的那么簡(jiǎn)單,因?yàn)樵贘ava應(yīng)用中經(jīng)常發(fā)生內(nèi)存泄漏。
本教程演示了什么是內(nèi)存泄漏,為什么會(huì)發(fā)生內(nèi)存泄漏以及如何預(yù)防內(nèi)存泄漏。
什么是內(nèi)存泄漏?
定義:如果對(duì)象在應(yīng)用中不再被使用,但由于它們?cè)谄渌胤奖灰?,垃圾回收卻不能移除它們(這樣就造成了很多內(nèi)存不能釋放,從而導(dǎo)致內(nèi)存溢出的現(xiàn)象。譯注)。
要理解這一定義,我們需要理解內(nèi)存中對(duì)象的狀態(tài)。下圖說明了那些是未使用,那些是未引用。
從圖中可以看到被引用對(duì)象和未引用對(duì)象(的范圍)。未引用對(duì)象可以被垃圾回收機(jī)制回收,而被引用對(duì)象不能被垃圾回收機(jī)制回收。未引用對(duì)象當(dāng)然是沒有使用的,因?yàn)闆]有其他對(duì)象引用了它。然而未使用對(duì)象并不都是未引用的。某些未使用的對(duì)象仍然被其他地方引用!這就是內(nèi)存泄漏起因。
為什么會(huì)發(fā)生內(nèi)存泄漏?
讓我們來下面的這個(gè)例子,看看為什么會(huì)發(fā)生內(nèi)存泄漏。在如下例子中,A對(duì)象引用了B對(duì)象。A的生命周期(t1-t4)比B的生命周期(t2-t3)要長(zhǎng)的多,當(dāng)B不再在應(yīng)用中被使用,A仍然持有對(duì)B的引用。這樣一來,垃圾回收機(jī)制不能從內(nèi)存中移除B。這很有可能導(dǎo)致內(nèi)存溢出問題,因?yàn)槿绻渌芏鄬?duì)象像A一樣,那么內(nèi)存中將會(huì)有很多不能被回收的對(duì)象,這將消耗大量?jī)?nèi)存空間。
也有可能的情況是B持有了大量對(duì)其他對(duì)象的引用。這些被B引用的對(duì)象同樣不會(huì)被回收掉。所有這些未使用的對(duì)象將會(huì)消耗寶貴的內(nèi)存空間。
如何預(yù)防內(nèi)存泄漏?
如下是一些預(yù)防內(nèi)存泄漏的快速技巧:
1、留意集合類,比如HashMap,ArrayList等等,因?yàn)樗麄兪莾?nèi)存泄漏經(jīng)常發(fā)生的地方。當(dāng)它們被聲明為靜態(tài)對(duì)象時(shí),他們的生命周期就和應(yīng)用的生命周期一樣長(zhǎng)。
2、留意事件監(jiān)聽器和回調(diào)。如果一個(gè)類注冊(cè)了監(jiān)聽器,但當(dāng)該類不再被使用后沒有注銷監(jiān)聽器,可能會(huì)發(fā)生內(nèi)存泄漏。
3、“如果一個(gè)類管理自己的內(nèi)存,程序員應(yīng)該警惕內(nèi)存泄漏。”[1],很多時(shí)候?qū)ο笾械闹赶蚱渌麑?duì)象成員變量需要設(shè)置成null(才能被回收)。
- 排查Java應(yīng)用內(nèi)存泄漏問題的步驟
- Java DWR內(nèi)存泄漏問題解決方案
- Java內(nèi)存泄漏問題處理方法經(jīng)驗(yàn)總結(jié)
- java虛擬機(jī)內(nèi)存溢出及泄漏實(shí)例
- Java中由substring方法引發(fā)的內(nèi)存泄漏詳解
- Android性能優(yōu)化之利用Rxlifecycle解決RxJava內(nèi)存泄漏詳解
- Java中關(guān)于內(nèi)存泄漏出現(xiàn)的原因匯總及如何避免內(nèi)存泄漏(超詳細(xì)版)
- 深入理解Java垃圾回收機(jī)制以及內(nèi)存泄漏
- 解析Java的JNI編程中的對(duì)象引用與內(nèi)存泄漏問題
- Java中的內(nèi)存泄漏
相關(guān)文章
@FeignClient?path屬性路徑前綴帶路徑變量時(shí)報(bào)錯(cuò)的解決
這篇文章主要介紹了@FeignClient?path屬性路徑前綴帶路徑變量時(shí)報(bào)錯(cuò)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07在Idea2020.1中使用gitee2020.1.0創(chuàng)建第一個(gè)代碼庫的實(shí)現(xiàn)
這篇文章主要介紹了在Idea2020.1中使用gitee2020.1.0創(chuàng)建第一個(gè)代碼庫的實(shí)現(xiàn),文中通過圖文示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-07-07JAVA設(shè)計(jì)模式之備忘錄模式原理與用法詳解
這篇文章主要介紹了JAVA設(shè)計(jì)模式之備忘錄模式,簡(jiǎn)單說明了備忘錄模式的概念、原理并結(jié)合實(shí)例形式分析了java備忘錄模式的具體定義及使用方法,需要的朋友可以參考下2017-08-08深入學(xué)習(xí)java ThreadLocal的源碼知識(shí)
ThreadLocal是一個(gè)本地線程副本變量工具類。主要用于將私有線程和該線程存放的副本對(duì)象做一個(gè)映射,各個(gè)線程之間的變量互不干擾,特別適用于各個(gè)線程依賴不通的變量值完成操作的場(chǎng)景。下面我們來詳細(xì)了解一下它吧2019-06-06SpringCloud微服務(wù)續(xù)約實(shí)現(xiàn)源碼分析詳解
這篇文章主要介紹了SpringCloud微服務(wù)續(xù)約實(shí)現(xiàn)源碼分析,服務(wù)續(xù)期和服務(wù)注冊(cè)非常相似,服務(wù)注冊(cè)在Eureka?Client程序啟動(dòng)之后開啟,并同時(shí)開啟服務(wù)續(xù)期的定時(shí)任務(wù)2022-11-11