程序员基本功04JAVA的内存回收
讀書筆記自己看的(O_O)
1、Java引用的功能和意義
程序員需要通過關(guān)鍵字new創(chuàng)建Java對象,即可視作為Java對象申請內(nèi)存空間,JVM會在堆內(nèi)存中為每個對象分配空間;當(dāng)一個Java對象失去引用,Java回收機(jī)制會自動清除它們。
2、Java引用與內(nèi)存回收之間的關(guān)系
只要還有引用變量引用該對象,垃圾回收機(jī)制就不會回收它。Java對象被創(chuàng)建出來后,垃圾回收機(jī)制會實(shí)時地監(jiān)控每一個對象的運(yùn)行狀態(tài),當(dāng)垃圾回收機(jī)制監(jiān)控到某一個對象不再被引用變量所引用時,立即回收機(jī)制就會回收它所占的空間。
JVM的垃圾回收機(jī)制采用有向圖方式管理內(nèi)存中的對象,可以方便的解決循環(huán)引用問題。采用有向圖來管理內(nèi)存中的對象具有較高的精度,但效率較低。
3、Java對象在內(nèi)存中的不同狀態(tài)
可達(dá)狀態(tài):有一個以上的引用變量引用它,程序可以通過引用變量來調(diào)用該對象的屬性和方法。
可恢復(fù)狀態(tài):程序中的對象不在有程序引用它。它將先進(jìn)入可恢復(fù)狀態(tài),回收機(jī)制準(zhǔn)備回收該對象所占內(nèi)存。在回收之前,系統(tǒng)會調(diào)用finalize方法進(jìn)行資源清理,如果系統(tǒng)在調(diào)用finalize方法重新讓變量引用該對象,這個對象會變成可達(dá)狀態(tài)。
不可達(dá)狀態(tài):該對象的所有關(guān)聯(lián)都被切斷,且系統(tǒng)調(diào)用finalize方法依然沒有使該對象變成可達(dá)狀態(tài),那么該對象將永久性失去引用。
當(dāng)某個對象被其他類的類變量引用時,只有該類被銷毀后,該對象才會進(jìn)入可恢復(fù)狀態(tài);當(dāng)某個對象被其他對象的實(shí)例變量引用時,只有當(dāng)引用該對象的對象被銷毀或變成不可達(dá)狀態(tài)后,該對象才會進(jìn)入不可達(dá)狀態(tài)。
程序創(chuàng)建一個對象,并把這個對象賦給一個引用變量,這個就是強(qiáng)引用,JVM不會回收強(qiáng)引用的Java對象,因此強(qiáng)引用是造成內(nèi)存泄漏的主要原因之一。
4、軟引用的作用和使用軟引用的注意點(diǎn)
軟引用需要通過SoftReferance類來實(shí)現(xiàn),當(dāng)系統(tǒng)內(nèi)存空間足夠時,對于只有軟引用的對象而言,它不會被回收,當(dāng)內(nèi)存不足時,系統(tǒng)將會回收它。軟引用通常用于內(nèi)存敏感的程序中,解決內(nèi)存緊張的難題。
5、弱引用的作用和使用弱引用的注意點(diǎn)
弱引用和軟引用相似,使用WeakReferancd類實(shí)現(xiàn),只是弱引用生存期更短,當(dāng)垃圾回收機(jī)制運(yùn)行時,不管系統(tǒng)內(nèi)存夠不夠,總會回收該對象所占內(nèi)存。
弱引用具有很大的不確定性,因?yàn)槊看卫厥諜C(jī)制執(zhí)行時都會回收弱引用所引用的對象,而垃圾回收機(jī)制不受程序員控制,因此程序獲取弱引用所引用的Java對象時必須小心空指針異常。
6、虛引用的作用和需引用的注意點(diǎn)
虛引用不能單獨(dú)使用,必須和引用隊(duì)列(ReferenceQueue)聯(lián)合使用。虛引用的主要作用是跟蹤對象被垃圾回收的狀態(tài),程序可以通過檢查與虛引用關(guān)聯(lián)的引用隊(duì)列中是否已經(jīng)包含指定虛引用,從而了解虛引用所引用對象是否即將被回收。
7、Java內(nèi)存泄漏原因
內(nèi)存泄漏:程序運(yùn)行過程中會不斷分配內(nèi)存空間,哪些不再使用的內(nèi)存空間應(yīng)該及時回收它們,從而保證系統(tǒng)能再次使用這些內(nèi)存,如果存在無用的內(nèi)存沒有被回收,那就是內(nèi)存泄漏。
不可達(dá)的對象由垃圾回收機(jī)制進(jìn)行回收,如果程序中的一些對象處于可達(dá)狀態(tài),但程序永遠(yuǎn)都不會訪問它們,那么它們所占的內(nèi)存也不會被回收,從而造成內(nèi)存泄漏。
8、Java內(nèi)存泄漏和C++內(nèi)存泄漏的差異
對于C++而言,對象占用的內(nèi)存空間必須由程序員顯示的回收,程序員可在合適的時機(jī)釋放它們。但是,Java程序來說,只要它們一直處于可達(dá)狀態(tài),垃圾回收機(jī)制就不會回收它們。
9、Java內(nèi)存回收機(jī)制的基本算法
垃圾回收機(jī)制主要完成倆件事:跟蹤并監(jiān)控每個Java對象,當(dāng)某個對象處于不可達(dá)狀態(tài)時,回收該對象所占的內(nèi)存;清理內(nèi)存分配,回收過程中產(chǎn)生的內(nèi)存碎片。這倆個工作量都不小,因此垃圾回收算法成為限制Java運(yùn)行效率的重要原因,實(shí)現(xiàn)高校JVM的一個重要方面就是提供高校的垃圾回收機(jī)制。
JVM垃圾回收機(jī)制判斷某個對象是否可以回收的唯一標(biāo)準(zhǔn)是:是否還有其他引用指向該對象。實(shí)際上,當(dāng)一個對象失去引用后,它不會被立即回收,只有等垃圾回收運(yùn)行時才會被回收。
https://www.cnblogs.com/sunniest/p/4575144.html(垃圾回收算法)
10、堆內(nèi)存的分代回收
分代回收的策略基于倆點(diǎn):絕大多數(shù)對象不會被長時間引用,這些對象在young代期間就會被回收;很老的對象和很新的對象之間很少存在相互引用的情況。對于young代的對象而言,大部分對象都會很快進(jìn)入不可達(dá)狀態(tài),少數(shù)對象能熬到垃圾回收執(zhí)行時,如果采用復(fù)制算法,只需要少量的復(fù)制成本,因此大部分垃圾回收器對young代都采用復(fù)制算法。
11、Young代、Old代和Permanent代的各自存儲對象
對young代采用復(fù)制算法只需遍歷那些處于可達(dá)狀態(tài)的對象;
old代的垃圾回收具有倆個特征:old代垃圾回收的執(zhí)行頻率無需太高,因?yàn)楹苌儆袑ο笏赖?#xff1b;每次對old代執(zhí)行垃圾回收需要更長的時間來完成。隨著時間的流逝,old代的對象會越來越多,因此old代的空間比young代空間更大。
12、Young代、Old代和permanent代的特定及適用的回收算法
對young代使用復(fù)制算法
對于old代,通常采用標(biāo)記壓縮算法,這種算法可以避免復(fù)制old代的大量對象
垃圾回收機(jī)制通常不會回收permanent代中的對象。
13、常見垃圾回收機(jī)制對堆內(nèi)存的回收細(xì)節(jié)
串行回收器:串行回收器對young代和old代的回收都是串行的,垃圾回收期間程序會暫停,具體策略為,young代采用串行復(fù)制算法,old代采用串行標(biāo)記壓縮算法。系統(tǒng)將Eden中的活動對象直接復(fù)制到To區(qū),如果對象占用內(nèi)存特別大,垃圾回收器會直接將其復(fù)制到old中。對于From區(qū)的活動對象,如果生存時間長,它將被復(fù)制到old代中,否則將被回收到To區(qū)中。完成復(fù)制后,Eden和From區(qū)剩下的均為不可達(dá)的對象,由系統(tǒng)直接回收,To區(qū)保存了活動對象,在下一次回收時,原To區(qū)變?yōu)镕rom區(qū),原From區(qū)變?yōu)門o區(qū)。
并行回收器:并行回收器對于young代采用與串行回收器基本象失的算發(fā),只是增加了cpu并行能力,即同時啟動多線程并行來執(zhí)行垃圾回收。并行回收器對于old代采用與串行回收器完全相同的回收算法,采用單線程、標(biāo)記整理的方式進(jìn)行回收。
并發(fā)壓縮回收器:對于young代,采用與并發(fā)回收器完全相同的算法;()
并發(fā)標(biāo)識-清理回收器(CMS):
?
14、設(shè)計開發(fā)內(nèi)存管理的小技巧
盡量使用直接量:
使用StringBuilder和StringBuffer進(jìn)行字符串連接:String代表不可變字符串,而StringBuilder和StringBuffer代表字符序列可變的字符串
盡早釋放無用對象的引用;
盡量少用靜態(tài)變量:JVM會將含有靜態(tài)變量的類存入到permanent代,這將導(dǎo)致
避免在經(jīng)常調(diào)用的方法、循環(huán)中創(chuàng)建Java對象
緩存經(jīng)常使用的對象:使用HashMap進(jìn)行緩存,直接使用某些開源的緩存項(xiàng)目
盡量不要使用finalize方法:垃圾回收器本省已經(jīng)嚴(yán)重制約程序性能,如果再使用finalize()進(jìn)行資源清理,這將導(dǎo)致垃圾回收器負(fù)擔(dān)更大,效率更差
考慮使用SoftReference:內(nèi)存夠時,它等同于普通引用,內(nèi)存不夠時,它會犧牲自己,釋放內(nèi)存
?
總結(jié)
以上是生活随笔為你收集整理的程序员基本功04JAVA的内存回收的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 程序员基本功03常见JAVA集合的实现细
- 下一篇: 程序员基本功05表达式中的陷阱