前言:
生的對立面不是死亡婶溯,而是遺忘。
生的對立面不是死亡偷霉,而是遺忘迄委。
生的對立面不是死亡,而是遺忘类少。
重要的事情說三遍叙身!請大家一定要好好記住這句話,這句話是我們整篇文章的精髓所在硫狞。
我信你個鬼信轿,你個世界上最帥最機(jī)智勇敢玉樹臨風(fēng)風(fēng)流倜儻的帥哥壞得很。
不信残吩?走著瞧财忽,扯不上去算我輸。
概念準(zhǔn)備:
VM 洋文全稱為Virtual Machine 泣侮,中文一般被譯為虛擬機(jī)即彪,虛擬機(jī)一般用來指通過軟件模擬的具有完整硬件系統(tǒng)功能的、運(yùn)行在一個完全隔離環(huán)境中的完整計(jì)算機(jī)系統(tǒng)活尊。
而 JVM則是代表java語言的虛擬機(jī)隶校,洋文全稱:Java Virtual Machine。
世界上第一款商用java虛擬機(jī)是Sun公司1996年在jdk1.0中發(fā)布的Sun Classic VM蛹锰,很早之前Sun Classic VM就已經(jīng)被廢棄掉了惠况,由HotSot VM虛擬機(jī)來代替。
扯蛋環(huán)節(jié):
既然你是要寫jvm內(nèi)存回收系列的學(xué)習(xí)筆記宁仔,那關(guān)java對象死亡有什么關(guān)系?
誒峦睡,這你就不對了翎苫,怎么能沒有關(guān)系呢,jvm回收的是什么榨了?是內(nèi)存煎谍,內(nèi)存被誰占著呢?java對象(主要)龙屉,那對象不死怎么回收他呢呐粘?
對象不死怎么就不能回收了满俗?
杠是吧,扛是吧作岖,扛是吧唆垃,我們把jvm虛擬機(jī)在垃圾回收過程中的角色理解為我們神話傳說中的閻王爺,按照古老的傳說痘儡,人只有死了之后靈魂才會被回收繼續(xù)投胎辕万,人活著就算再廢物也不能直接讓他投胎了,必須要等他死了才行沉删,而且渐尿,在人沒死之前直接回收這個人的靈魂可能會導(dǎo)致一些很嚴(yán)重的問題,比如你回收個美國的殺人犯的靈魂矾瑰,那肯定對這個世界不會產(chǎn)生什么特別大的影響砖茸,但是萬一你要不小心抽到特朗普了,那可能就會引起大亂子殴穴。
jvm也是這么考慮的凉夯,萬一你這個對象別的地方正用著呢,jvm直接給他回收了推正,就有可能直接導(dǎo)致整個應(yīng)用的崩潰恍涂。
微劇場:
大家好,我是一個java對象植榕,我叫阿呆再沧。萬萬沒想到的是,我現(xiàn)在竟然要證明自己死了尊残。
事情是這樣的炒瘸,我是一個廢材對象,當(dāng)主人把我創(chuàng)造出來時(shí)寝衫,我滿以為自己會光芒萬丈大有作為成為java對象之王顷扩,可是這貨把我new出來之后他娘的竟然把我給忘了,他和其他的對象嬉戲打鬧慰毅,我卻只能在角落里傷心假笑隘截,我感覺整個運(yùn)行環(huán)境的天空都變成了灰色,我不想活了汹胃,我太難了婶芭,于是我跑到j(luò)ava虛擬機(jī)內(nèi)存回收局懇請可以將我回收掉,像我這種廢材沒人在乎的對象真的就是活著浪費(fèi)內(nèi)存了着饥。
可是java虛擬機(jī)內(nèi)存回收局殘忍地拒絕了我犀农,還讓我哪涼快哪呆著去,當(dāng)然我并不打算為此退縮宰掉,在我的威逼利誘(苦苦哀求)下呵哨,java虛擬機(jī)內(nèi)存回收局終于告訴了我事情的真相赁濒。
很抱歉呢∶虾Γ可憐的阿呆先生拒炎,這個世界仍然還有人記得你,我們并不能把你回收掉
還有人記得...記得我纹坐?(雙眼閃爍著淚花)
聽完阿呆屁顛屁顛邁著扭秧歌的魔鬼的步伐回去了枝冀。(尼瑪,剛才還想自殺呢耘子,節(jié)操呢果漾?變這么快)
當(dāng)然,java虛擬機(jī)內(nèi)存回收局肯定不是隨隨便便就把阿呆認(rèn)定死亡的谷誓,經(jīng)歷過幾十年的發(fā)展绒障,該機(jī)構(gòu)研發(fā)了一款java對象驗(yàn)死儀,原理主要是基于引用計(jì)數(shù)和可達(dá)性分析算法這兩個算法捍歪,那么下面我們就依次來介紹這兩種算法户辱。
引用計(jì)數(shù)算法:
官方概念:引用計(jì)數(shù)算法是通過判斷對象的引用數(shù)量來決定對象是否可以被回收。
Hello h = new Hello(); 其中h就稱之為Hello對象的引用糙臼,即我們可以通過h來訪問到我們的Hello對象庐镐。
在這里我們可以理解為,假如B對象中包含A對象的引用变逃,就意味著B對象和A對象有所聯(lián)系必逆,即B對象記得A對象。當(dāng)B對象因?yàn)橐恍┰虮热缫馔馑劳隼柯遥夏臧V呆名眉,韓國偶像劇等,不記得A對象的存在了凰棉,則我們稱之為B遺忘了A损拢,我說嘛,我肯定可以扯到這里的撒犀。
每當(dāng)有一個新的對象和A對象產(chǎn)生聯(lián)系時(shí)福压,即引用A對象,那么A對象的引用計(jì)數(shù)器就+1或舞,如果誰不小心把A對象給忘了隧膏, 則意味著引用失效了,那么A對象的引用計(jì)數(shù)器就-1嚷那,當(dāng)A對象的引用計(jì)數(shù)器變成0的時(shí)候,意味著虛擬機(jī)中已經(jīng)沒有任何對象還保留著A對象的引用了杆煞,即除了A對象自己魏宽,沒有對象記得A對象的存在了腐泻,這個時(shí)候A對象就會被判定為死亡,被內(nèi)存回收掉队询。
這個時(shí)候可能有善良的小伙伴問了派桩,A對象那么可愛,為什么要回收掉它呢蚌斩,留著它不好嗎铆惑。
現(xiàn)在我們回歸引用的概念,A對象引用計(jì)數(shù)器為0意味著再也沒有任何一個對象可以訪問到A對象了送膳,側(cè)面就說明了A對象再也不能被使用员魏,變成了一個徹徹底底的廢對象。
所以:生的對立面不是死亡叠聋,而是遺忘撕阎。
這么一想,引用計(jì)數(shù)算法的確還不錯碌补,這樣死亡的對象都會被正確識別出來虏束,從而回收掉。
年輕人厦章,你還是想的太簡單了镇匀。你忘了這個世界上有奇葩的存在了嗎?且看下面這段對話:
A:我詛咒你今年禿頭袜啃!
B:詛咒反貪
A:我也反彈
B:我再反彈
此處省略N個字汗侵。
沒完沒了,放在對象也是這樣囊骤,加入A對象包含了B對象的引用晃择,B對象又包含了A對象的引用,因?yàn)橄嗷ヒ靡参铮麄兊囊糜?jì)數(shù)器都無法為0宫屠,也就不會被回收掉了。
所以引用計(jì)數(shù)在目前主流的java虛擬機(jī)中被廢棄掉了滑蚯。
可達(dá)性分析算法:
官方概念:可達(dá)性分析算法是通過判斷對象的引用鏈?zhǔn)欠窨蛇_(dá)來決定對象是否可以被回收浪蹂。
從GC Roots作為起點(diǎn),向下搜索它們引用的對象告材,可以生成一棵引用樹坤次,樹的節(jié)點(diǎn)視為可達(dá)對象,反之視為不可達(dá)斥赋。圖長這樣:
這個算法就好玩多了缰猴,我們可以把這個算法看作是一個巨大的傳銷集團(tuán),它是怎么判斷對象是否死亡的呢疤剑?
我們可以把GC Roots看作是傳銷頭子滑绒,虛擬機(jī)會從傳銷頭子往下依次搜索它的下線闷堡,如果你能被搜索到,那么你就是在傳銷組織里面的疑故,比如2 3 4 都在傳銷集團(tuán)里面杠览,而 5 6 7 呢。
5 6 7就是那些沒有組織的野傳銷纵势,傳銷集團(tuán)怎么會容忍這些野傳銷存在呢踱阿,于是他們都被判斷為死亡。
所以:生的對立面不是死亡钦铁,而是遺忘软舌。
而 5 6 7 這三個對象都被忘掉了,因?yàn)樗麄儧]有組織育瓜,組織自然沒有辦法差遣他們葫隙,發(fā)揮他們的價(jià)值,于是它們變成廢對象被回收掉了躏仇。
的確優(yōu)勢明顯恋脚,隨便你們反彈,沒有組織你們都要完蛋焰手。
而GC Roots也不是誰都能當(dāng)?shù)脑忝瑁陂L期的實(shí)踐中,發(fā)現(xiàn)有四類對象擁有成為傳銷頭子书妻,呸船响,Gc Roots的潛質(zhì),他們分別是:
-虛擬機(jī)棧(棧幀中的本地變量表)中的引用對象躲履。
-方法區(qū)中的類靜態(tài)屬性引用的對象见间。
-方法區(qū)中的常量引用的對象。
-本地方法棧中JNI(Native方法)的引用對象
可達(dá)性分析算法也是被廣泛使用的對象判定算法
沒了工猜。
下面到技術(shù)總結(jié)環(huán)節(jié):
總結(jié)
本篇文章我們可謂是用盡了廢話來幫助剛開始學(xué)習(xí)java或者jvm的朋友們徹底理解jvm判斷java對象死亡的兩種算法米诉,再學(xué)習(xí)jvm的過程中,發(fā)現(xiàn)很多jvm書籍篷帅,博客都寫的比較學(xué)術(shù)史侣,讓新手們望而卻步,導(dǎo)致很多人看了一遍以為自己懂了魏身,但是過了幾天之后再想?yún)s沒有辦法想起來惊橱,根本原因還是在于并沒有徹底的理解這些知識.還是需要繼續(xù)努力去消化和吸收這些知識.