JVM內(nèi)存管理—內(nèi)存回收—哪些內(nèi)存需要回收橙困?

哪些區(qū)域需要回收

運(yùn)行時(shí)內(nèi)存分為5個(gè)區(qū)域:程序計(jì)數(shù)器、虛擬機(jī)棧哼转、本地方法棧猫态、堆义辕、方法區(qū)基显,這些區(qū)域是如何回收的销部?

1-程序計(jì)數(shù)器雨膨、虛擬機(jī)棧、本地方法棧

這3個(gè)區(qū)域是隨著線程而生,隨著線程而滅,棧中的棧幀數(shù)據(jù)隨著方法的調(diào)用到結(jié)束有條不紊的進(jìn)行著入棧出棧,每一個(gè)棧幀中分配多少內(nèi)部基本上在類結(jié)構(gòu)確定下來(類加載)就已知了蔬充。內(nèi)存分配和回收具有確定性愕提,隨著方法的結(jié)束或者線程的結(jié)束后,內(nèi)存自然就會(huì)被回收了如输。

2- java堆和方法區(qū)

一個(gè)接口中的多個(gè)實(shí)現(xiàn)類需要的內(nèi)存可能不一樣缎谷,一個(gè)方法的多個(gè)分支需要的內(nèi)存也不一樣,我們只有在程序處于執(zhí)行期間才能知道會(huì)創(chuàng)建哪些對(duì)象春感,對(duì)這部分的內(nèi)存分配和回收是動(dòng)態(tài)的,垃圾回收主要關(guān)注的是這部分的內(nèi)存竟纳。

判斷對(duì)象是“生”是“死”?

引用計(jì)數(shù)算法

java虛擬機(jī)沒有采用引用計(jì)數(shù)算法來判斷對(duì)象是否生存颅筋,主要考慮的是它很難解決對(duì)象之間的相互循環(huán)引用的問題。

可達(dá)性分析算法(Reachablity Analysis)

基本思路是:從每一個(gè)GC Roots出發(fā)找到它所有可達(dá)的對(duì)象用押,走過的路徑成為引用鏈蜻拨,被引用鏈串起來的就是存活對(duì)象厘灼;其他的雖然存在引用關(guān)系闪朱,但是GC Roots不可達(dá)的,判定為可回收對(duì)象。澜术、
GC Roots :可作為的對(duì)象包含以下幾種:

  1. 虛擬機(jī)棧(棧幀中本地變量表)中引用的對(duì)象
  2. 方法區(qū)中類靜態(tài)屬性引用的對(duì)象
  3. 方法區(qū)常量引用的對(duì)象
  4. 本地方法棧中JNI(Native Method)引用的對(duì)象

引用與緩存

為了更細(xì)致的管理對(duì)象的內(nèi)存艺蝴,對(duì)象引用進(jìn)行了擴(kuò)展,分為:強(qiáng)引用(Strong Reference)鸟废、軟引用(Soft Reference)猜敢、弱引用(Weak Reference)、虛引用(Phantom Reference盒延,也叫幽靈引用)缩擂。

強(qiáng)引用
  • Object obj = new Object(); 這種通過關(guān)鍵字new出來的對(duì)象就屬于強(qiáng)引用,普遍存在的添寺,只要這種引用還關(guān)聯(lián)著對(duì)象胯盯,就不會(huì)被垃圾回收器回收。
  • **內(nèi)存空間不夠時(shí)计露,不會(huì)進(jìn)行垃圾回收博脑,而是直接拋出內(nèi)存溢出異常 **
軟引用

用來描述有用但是并不必需的對(duì)象,在系統(tǒng)將要發(fā)生內(nèi)存溢出異常之前票罐,JVM將會(huì)把這些對(duì)象標(biāo)記成垃圾數(shù)據(jù)叉趣,并對(duì)這些標(biāo)記的數(shù)據(jù)進(jìn)行二次回收,若回收后還是沒有足夠的內(nèi)存分配该押,才會(huì)拋出內(nèi)存溢出的異常疗杉。 用法: 用來實(shí)現(xiàn)內(nèi)存敏感的緩存

import java.lang.ref.SoftReference;
class ReferenceTest{
    Object obj = new Object();//強(qiáng)引用
    SoftReference<Object> sr = new SoftReference<Object>(obj);//關(guān)聯(lián)軟引用
    // 取消強(qiáng)引用,只保留軟引用
    obj=null沈善;
    pass(...);
    //通用的處理乡数,以及softreference的復(fù)用模式
    if(sr.get() != null){
        Obeject getRef = sr.get();
        use(getRef);
    }else{
        Object newObj = new Object();
        sr = new SoftReference(newObj);//重建軟引用
    }
}
  • 注意
    1.在虛擬機(jī)內(nèi)存空間足夠大的時(shí)候是不會(huì)發(fā)生內(nèi)存回收的,而且GC的優(yōu)先級(jí)最低闻牡,只有所有線程都停止時(shí)才有可能執(zhí)行GC(即使使用System.gc()也只是告訴JVM這是一個(gè)執(zhí)行GC的好時(shí)機(jī)净赴,但是實(shí)際上JVM會(huì)自己決斷是否達(dá)到了這個(gè)條件,比如沒有線程正在執(zhí)行罩润,這是GC這個(gè)守護(hù)線程就會(huì)執(zhí)行)玖翅,因?yàn)镚C有一定的代價(jià)。所以與軟引用關(guān)聯(lián)的對(duì)象在內(nèi)存充足時(shí)是不會(huì)發(fā)生的割以,只有處于內(nèi)存溢出的邊緣才會(huì)發(fā)生回收操作金度。
    2.雖然與軟引用關(guān)聯(lián)的對(duì)象可能會(huì)被收回,但保存這個(gè)軟引用關(guān)系的SoftReference變量并不一定會(huì)被回收严沥,所以出現(xiàn)了ReferenceQueue來管理這些變量猜极。
弱引用
  • 弱引用描述的是非必需的對(duì)象:被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次GC回收發(fā)生之前,當(dāng)GC工作時(shí)消玄,無論當(dāng)前空間是否足夠跟伏,都會(huì)回收只被弱引用關(guān)聯(lián)的對(duì)象丢胚。
  • 用法:一般會(huì)和ReferenceQueue進(jìn)行關(guān)聯(lián)
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
public class WeakReferenceTest{
    public static void main(Stting[] args) throws Exception{
        Object obj = new Object();
        //ReferenceQueue的作用:
        //當(dāng)弱引用關(guān)聯(lián)的對(duì)象被標(biāo)記為垃圾,準(zhǔn)備回收時(shí)受扳,
        //會(huì)自動(dòng)把保存弱引用的對(duì)象WeakReference放到ReferenceQueue中携龟,等待被處理
        //主要目的是:引用關(guān)聯(lián)的對(duì)象被回收了,但存儲(chǔ)引用的對(duì)象沒有及時(shí)回收會(huì)造成
        //內(nèi)存膨脹
        ReferenceQueue<Object> rf = new ReferenceQueue<Object>();
        WeakReference<Object> wf = new WeakReference<Object>(obj,rf);
        WeakReference<Object> wf_q = null;
                // poll方法勘高,刪除隊(duì)尾引用并返回
        while(wf_q = rf.poll()!= null){
            // do something for remove reference
        }
    }
}
虛引用
  • 最弱的一種引用關(guān)系峡蟋,無法通過虛引用來獲取對(duì)象的實(shí)例
  • 用途:僅僅是在這個(gè)對(duì)象被回收時(shí)收到一個(gè)系統(tǒng)的通知。
總結(jié)

對(duì)于軟引用和弱引用华望,被GC標(biāo)記為垃圾準(zhǔn)備回收時(shí)會(huì)清除對(duì)應(yīng)的引用蕊蝗,即get方法返回null,然后放入綁定的引用隊(duì)列中立美,理論上此時(shí)沒有真正被回收匿又,只是沒有辦法在訪問到方灾;但是對(duì)于虛引用則是在發(fā)生回收時(shí)放入隊(duì)列建蹄,也是唯一一種確認(rèn)對(duì)象被回收而加入隊(duì)列的引用,可以利用這一特性做一些有趣的事裕偿。


finalize()越獄

通過一條到墻外的地下通道(finalize)洞慎、一列快速列車(F-Queue)的驚險(xiǎn)越獄大片

  • 可達(dá)性分析發(fā)現(xiàn)這個(gè)對(duì)象沒有到GC Roots的引用鏈(快到砍頭的時(shí)候了),進(jìn)行第一次標(biāo)記嘿棘,如果對(duì)象沒有覆蓋Object的finalize方法劲腿,或者已經(jīng)執(zhí)行過了一次finalize方法,則這個(gè)對(duì)象的finalize不會(huì)執(zhí)行鸟妙,等待下一次GC被回收(蠢蛋和倒霉蛋的組合焦人,一個(gè)不知道這個(gè)秘密通道,一個(gè)越獄失敗被抓了回來成為重點(diǎn)照顧對(duì)象重父,沒日沒夜的毒打花椭,只能等死了)
  • 如果覆蓋了finalize方法但還沒有執(zhí)行(已經(jīng)踩好點(diǎn)了,還在做最后的精密計(jì)劃房午,天一黑矿辽,就行動(dòng)),將這個(gè)對(duì)象放到F-Queue中等待執(zhí)行finalize方法(通過地下秘密通道到達(dá)獄外郭厌,此時(shí)列車也到了袋倔,正在排隊(duì)刷卡上車...)
  • 以低優(yōu)先級(jí)執(zhí)行F-Queue中對(duì)象的finalize方法,進(jìn)行第二次標(biāo)記折柠,如果finalize中將自己對(duì)象的引用與外面的引用鏈上的對(duì)象建立了鏈接宾娜,則將其移出F-Queue,成功逃脫回收(滴扇售,學(xué)生卡前塔,上車落座贾陷,系好安全帶,老司機(jī)要飆車了)嘱根,如果沒有建立與引用鏈的鏈接髓废,則等待下一次GC被回收(滴,余額不足该抒,請(qǐng)及時(shí)充值慌洪,司機(jī)說窮鬼,沒錢還想做快速列車凑保。哎哎哎~冈爹,老司機(jī)帶帶我呀,帶帶我呀欧引,帶我呀频伤,我呀,呀...曾經(jīng)的秋名山車神遺棄在角落芝此。)

進(jìn)行了兩次標(biāo)記:第一次標(biāo)記是篩選有哪些finalize方法是需要執(zhí)行的憋肖;第二次標(biāo)記是哪些finalize方法關(guān)聯(lián)了引用鏈,將其移出隊(duì)列婚苹。

public class SaveSelfTest {
    public static Scofield BreakAway= null;//逃生專列
    public static void main(String[] args) throws Exception{
        Scofield michael = new Scofield();
        michael.sayHi();
        
        //第一次逃脫岸更,成功
        michael = null;//置為null,觸發(fā)回收的條件
        System.gc();
        Thread.sleep(200);
        
        if(BreakAway != null){
            BreakAway.sayHi();
        }else{
            util.print("ScoField:Please save me,I'll dead next morning!");
        }
        
        //第二次逃脫膊升,失敗怎炊,finalize函數(shù)只能最多被執(zhí)行一次
        BreakAway = null;
        System.gc();
        Thread.sleep(200);
        
        if(BreakAway != null){
            BreakAway.sayHi();
        }else{
            util.print("ScoField:Please save me,I'll dead next morning!");
        }
        
        System.exit(0);
    }

}
class Scofield{
    public void sayHi(){
        util.print("Hi, I'm Michael ScoField!");
    }
    @Override
    protected void  finalize() throws Throwable{
        super.finalize();//Object
        util.print("Scofield gets on car!");
        SaveSelfTest.BreakAway = this;//關(guān)聯(lián)引用鏈
    }
}
class util{
    public static void print(String str){
        System.out.println(str);
    }
}
/* Output
Hi, I'm Michael ScoField!
Scofield gets on car!
Hi, I'm Michael ScoField!
ScoField:Please save me,I'll dead next morning!
*/

參考鏈接
http://www.cnblogs.com/jiangyi-uestc/p/5679331.html
http://www.importnew.com/14115.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市廓译,隨后出現(xiàn)的幾起案子评肆,更是在濱河造成了極大的恐慌,老刑警劉巖非区,帶你破解...
    沈念sama閱讀 218,607評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件瓜挽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡院仿,警方通過查閱死者的電腦和手機(jī)秸抚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,239評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來歹垫,“玉大人剥汤,你說我怎么就攤上這事∨挪遥” “怎么了吭敢?”我有些...
    開封第一講書人閱讀 164,960評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)暮芭。 經(jīng)常有香客問我鹿驼,道長(zhǎng)欲低,這世上最難降的妖魔是什么峻呕? 我笑而不...
    開封第一講書人閱讀 58,750評(píng)論 1 294
  • 正文 為了忘掉前任也搓,我火速辦了婚禮吕世,結(jié)果婚禮上爵嗅,老公的妹妹穿的比我還像新娘。我一直安慰自己需了,他們只是感情好还栓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,764評(píng)論 6 392
  • 文/花漫 我一把揭開白布锦庸。 她就那樣靜靜地躺著块蚌,像睡著了一般闰非。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上峭范,一...
    開封第一講書人閱讀 51,604評(píng)論 1 305
  • 那天财松,我揣著相機(jī)與錄音,去河邊找鬼纱控。 笑死辆毡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的其徙。 我是一名探鬼主播胚迫,決...
    沈念sama閱讀 40,347評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼喷户,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼唾那!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起褪尝,我...
    開封第一講書人閱讀 39,253評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤闹获,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后河哑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體避诽,經(jīng)...
    沈念sama閱讀 45,702評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,893評(píng)論 3 336
  • 正文 我和宋清朗相戀三年璃谨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了沙庐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,015評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡佳吞,死狀恐怖拱雏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情底扳,我是刑警寧澤铸抑,帶...
    沈念sama閱讀 35,734評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站衷模,受9級(jí)特大地震影響鹊汛,放射性物質(zhì)發(fā)生泄漏蒲赂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,352評(píng)論 3 330
  • 文/蒙蒙 一刁憋、第九天 我趴在偏房一處隱蔽的房頂上張望滥嘴。 院中可真熱鬧,春花似錦至耻、人聲如沸氏涩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,934評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽是尖。三九已至,卻和暖如春泥耀,著一層夾襖步出監(jiān)牢的瞬間饺汹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,052評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工痰催, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兜辞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,216評(píng)論 3 371
  • 正文 我出身青樓夸溶,卻偏偏與公主長(zhǎng)得像逸吵,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子缝裁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,969評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容