以前看過很多次關(guān)于垃圾回收相關(guān)的文章,都只是看過就忘記了,沒有好好的整理一下,發(fā)現(xiàn)寫文章可以強(qiáng)化自己的記憶。
java與C,c++有很大的不同就是java語言開發(fā)者不需要關(guān)注內(nèi)存信息,不會(huì)顯式的直接操作內(nèi)存,而是通過jvm虛擬機(jī)來實(shí)現(xiàn)。 java虛擬機(jī)運(yùn)行的時(shí)候內(nèi)存分配圖如下圖:
jvm虛擬機(jī)棧:一個(gè)是線程獨(dú)有的,每次啟動(dòng)一個(gè)線程,就創(chuàng)建一個(gè)jvm虛擬機(jī)棧,線程退出的時(shí)候就銷毀。這里面主要保存線程本地變量名和局部變量值。 本地方法棧: 調(diào)用本地jni方法的時(shí)候而創(chuàng)建的。這里分配的jvm之外的內(nèi)存空間。方法調(diào)用結(jié)束之后銷毀。 pc寄存器 : 這個(gè)保存線程當(dāng)前執(zhí)行的字節(jié)碼指令 堆:主要保存創(chuàng)建的對(duì)象。 方法區(qū):保存class相關(guān)的信息。主要是class的一個(gè)內(nèi)存結(jié)構(gòu)信息 常量池:方法區(qū)的一部分,主要保存class內(nèi)存結(jié)構(gòu)中常量值 例如String值,public static final 類型的值
我們這里說的垃圾回收,主要是java虛擬機(jī)對(duì)堆內(nèi)存區(qū)域的回收。
1 首先的問題是:jvm如何知道那些對(duì)象需要回收 ?目前有兩種算法
在root搜索算法的里面,我們說的引用這里都指定的是強(qiáng)引用關(guān)系。所謂強(qiáng)引用關(guān)系,就是通過用new 方式創(chuàng)建的對(duì)象,并且顯示關(guān)聯(lián)的對(duì)象
以上就是代表的是強(qiáng)引用關(guān)系,變量obj 強(qiáng)引用了 Object的一個(gè)對(duì)象。 java里面有四種應(yīng)用關(guān)系,從強(qiáng)到弱分別為: Strong Reference(強(qiáng)引用) –>Weak Reference (弱引用) -> Soft Reference(軟引用) – > Phantom Reference(引用)
Strong Reference : 只有在引用對(duì)象root不可達(dá)的情況下才會(huì)標(biāo)識(shí)為可回收,垃圾回收才可能進(jìn)行回收 Weak Reference :即使在root算法中 其引用的對(duì)象root可達(dá)到,但是如果jvm堆內(nèi)存 不夠的時(shí)候,還是會(huì)被回收。 Soft Reference : 無論其引用的對(duì)象是否root可達(dá),在響應(yīng)內(nèi)存需要時(shí),由垃圾回收判斷是否需要回收。 Phantom Reference :在回收器確定其指示對(duì)象可另外回收之后,被加入垃圾回收隊(duì)列.
下面可以看一個(gè)測(cè)試
這里創(chuàng)建大約1000個(gè) 10K的 Weak Reference 對(duì)象,最后打印的結(jié)果是:被回收的對(duì)象數(shù):767,這里ReferenceObject如果設(shè)置為1K的話,最后的打印結(jié)果是0 這個(gè)例子并不嚴(yán)謹(jǐn),但是卻說明了被Weak Reference的對(duì)象在一定的時(shí)候會(huì)被jvm回收,但是強(qiáng)引用就不會(huì)出現(xiàn)這種狀態(tài)。 |
|