新聞中心
Hello 大家好,我是鴨血粉絲,2020 注定是一個(gè)不平凡的一年,很多小伙伴在后臺(tái)和星球留言都說(shuō)今年的工作不好找,也有應(yīng)屆生小伙伴給阿粉發(fā)消息問(wèn)阿粉所在的公司今年是否招應(yīng)屆生,阿粉也只能幫小伙伴問(wèn)問(wèn) HR,但是阿粉也做不了主。

公司主營(yíng)業(yè)務(wù):網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè)、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)公司是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶帶來(lái)驚喜。創(chuàng)新互聯(lián)公司推出贛榆免費(fèi)做網(wǎng)站回饋大家。
剛好前幾天一個(gè)小伙伴在微信上問(wèn)阿粉,說(shuō)是面試一家公司被問(wèn)到 Java GC 相關(guān)的東西,雖然平時(shí)也有準(zhǔn)備,但是回答起來(lái)總是零零散散,感覺(jué)沒(méi)有邏輯。其實(shí)阿粉也能理解,現(xiàn)在面試都是一種問(wèn)答模式,一個(gè)隨便問(wèn)問(wèn),一個(gè)死記硬背,很多時(shí)候面試前準(zhǔn)備的好好的一到面試的時(shí)候可能緊張就給忘了,事后感覺(jué)自己表現(xiàn)的不好。
這篇文章給大家舉個(gè)例子,在遇到一個(gè)問(wèn)題或者知識(shí)點(diǎn)的時(shí)候要怎么去理解和學(xué)習(xí)。
Java GC
目標(biāo)
遇到一個(gè)問(wèn)題或者一個(gè)知識(shí)點(diǎn),我們要理解和明白是要解決什么問(wèn)題的。說(shuō)到 Java GC 那這個(gè) GC 的目的是什么呢?很顯然是回收內(nèi)存,因?yàn)閮?nèi)存是有限的,隨著程序中創(chuàng)建的對(duì)象越來(lái)越多,如果進(jìn)行回收就會(huì)導(dǎo)致內(nèi)存越來(lái)越大,最后程序就會(huì)出現(xiàn)異常。既然目的是為了回收內(nèi)存,那么新的問(wèn)題來(lái)了,哪些對(duì)象可以被回收呢?什么時(shí)候進(jìn)行回收呢?怎么回收呢?
哪些對(duì)象可以被回收
簡(jiǎn)單來(lái)說(shuō)就是無(wú)用的對(duì)象可以被回收,那么換句話說(shuō),如果定義一個(gè)對(duì)象是無(wú)用的呢?這里主要有兩種方法,一個(gè)叫引用計(jì)數(shù)法,一個(gè)叫可達(dá)性分析法。
引用計(jì)數(shù)
引用計(jì)數(shù)說(shuō)的是如果一個(gè)對(duì)象被別的對(duì)象進(jìn)行了一次引用,那么該對(duì)象會(huì)有一個(gè)引用計(jì)數(shù)器,這個(gè)計(jì)數(shù)器就會(huì)加一;如果被釋放一下,引用計(jì)數(shù)器就會(huì)減一。當(dāng)引用計(jì)數(shù)器的計(jì)數(shù)為 0 的時(shí)候就表示這個(gè)對(duì)象是無(wú)用的,此時(shí)就可以對(duì)這樣對(duì)象進(jìn)行回收了。表面上看好像挺合理的,實(shí)現(xiàn)起來(lái)也很方便,但是仔細(xì)一想就會(huì)發(fā)現(xiàn)有問(wèn)題。既循環(huán)引用的問(wèn)題,比如對(duì)象 A 引用了對(duì)象 B,但是對(duì)象 B 當(dāng)中也引用了對(duì)象 A,那么這個(gè)時(shí)候?qū)ο?A 和對(duì)象 B 的引用計(jì)數(shù)器的計(jì)數(shù)都不會(huì)是 0,但是這兩個(gè)對(duì)象都沒(méi)有被其他對(duì)象引用,理論上來(lái)說(shuō)這兩個(gè)對(duì)象都是可以被回收的。
從上面看到,這種方案是有問(wèn)題的會(huì)導(dǎo)致內(nèi)存泄露。隨之而來(lái)的就出現(xiàn)了另一種方案,可就是可達(dá)性分析。
可達(dá)性分析
可達(dá)性分析說(shuō)的是從 GCRoots 的點(diǎn)作為起點(diǎn),向下搜索,當(dāng)找不到任何引用鏈的時(shí)候表示該對(duì)象為垃圾對(duì)象。那么哪些對(duì)象可以被認(rèn)為是 Roots 節(jié)點(diǎn)呢?有 Java 棧中的對(duì)象,方法區(qū)的靜態(tài)屬性和常量以及本地方法棧中的對(duì)象。從這幾種對(duì)象依次向下搜索,如果沒(méi)有能達(dá)到 Roots 節(jié)點(diǎn)的對(duì)象就是垃圾對(duì)象,就說(shuō)明可以被回收。
如下圖所有,對(duì)象 A,B,C都能找到與 Roots 節(jié)點(diǎn)的聯(lián)系,但是對(duì)象 D,E,F(xiàn) 三個(gè)并不能找到與 Roots 節(jié)點(diǎn)的聯(lián)系,也就是不可達(dá),所以 DEF 這三個(gè)對(duì)象就是垃圾對(duì)象。
什么時(shí)候回收
上面的兩種方案解決了哪些對(duì)象能被回收,那么下個(gè)問(wèn)題,就是什么時(shí)候進(jìn)行垃圾回收呢?在排除人為調(diào)用的時(shí)候,垃圾回收都是發(fā)生在為新生對(duì)象進(jìn)行內(nèi)存分配的時(shí)候,這個(gè)時(shí)候如果內(nèi)存空間不足就會(huì)觸發(fā) GC 進(jìn)行垃圾回收。
怎么回收
上面我們知道了哪些對(duì)象可以被回收,也知道我們應(yīng)該什么時(shí)候進(jìn)行回收,那下面要解決的就是如何進(jìn)行垃圾回收了。垃圾回收根據(jù)實(shí)現(xiàn)的方式不同有多種不同的算法實(shí)現(xiàn)。比如有標(biāo)記清除算法,復(fù)制算法,標(biāo)記整理算法,分代回收算法,下面簡(jiǎn)單介紹一下,想深入了解的可以自行去研究一下。
標(biāo)記清除算法
標(biāo)記清除算法很好理解,主要就是執(zhí)行兩個(gè)動(dòng)作,一個(gè)是標(biāo)記,另一個(gè)是對(duì)進(jìn)行標(biāo)記的對(duì)象內(nèi)存進(jìn)行清除回收。這個(gè)算法有個(gè)問(wèn)題就是會(huì)出現(xiàn)內(nèi)存碎片化嚴(yán)重。如下圖所示:
從上圖中可以看到,在進(jìn)行內(nèi)存回收后出現(xiàn)了嚴(yán)重的內(nèi)存碎片化,這就導(dǎo)致在分配某些大對(duì)象的時(shí)候仍然會(huì)出現(xiàn)內(nèi)存不夠的情況,但是總體內(nèi)存確是夠的。
復(fù)制算法
復(fù)制算法的實(shí)現(xiàn)方式比較簡(jiǎn)潔明了,就是霸道的把內(nèi)存分成兩部分,在平時(shí)使用的時(shí)候只用其中的固定一份,在當(dāng)需要進(jìn)行 GC 的時(shí)候,把存活的對(duì)象復(fù)制到另一部分中,然后將已經(jīng)使用的內(nèi)存全部清理掉。如下圖:
從上圖可以看到解決了標(biāo)記清除的內(nèi)存碎片化問(wèn)題,但是很明顯復(fù)制算法有另一個(gè)問(wèn)題,那就是內(nèi)存的使用率大大下降,能使用的內(nèi)存只有原來(lái)的一半了。
標(biāo)記整理算法
既然標(biāo)記清除和復(fù)制算法各有優(yōu)缺點(diǎn),那自然的我們就想到是否可以把這兩種算法結(jié)合起來(lái),于是就出現(xiàn)了標(biāo)記整理算法。標(biāo)記階段是標(biāo)記清除算法一樣,先標(biāo)記出需要回收的部分,不過(guò)清除階段不是直接清除,而是把存活的對(duì)象往內(nèi)存的一端進(jìn)行移動(dòng),然后清除剩下的部分。如下圖:
標(biāo)記整理的算法雖然可以解決上面兩個(gè)算法的一些問(wèn)題,但是還是需要先進(jìn)行標(biāo)記,然后進(jìn)行移動(dòng),整個(gè)效率還是偏低的。
分代回收算法
分代回收算法是目前使用較多的一種算法,這個(gè)不是一個(gè)新的算法,只是將內(nèi)存進(jìn)行的劃分,不同區(qū)域的內(nèi)存使用不同的算法。根據(jù)對(duì)象的存活時(shí)間將內(nèi)存的劃分為新生代和老年代,其中新生代包含 Eden 區(qū)和 S0,S1。在新生代中使用是復(fù)制算法,在進(jìn)行對(duì)象內(nèi)存分配的時(shí)候只會(huì)使用 Eden 和 S0 區(qū),當(dāng)發(fā)生 GC 的時(shí)候,會(huì)將存活的對(duì)象復(fù)制到 S1 區(qū),然后循環(huán)往復(fù)進(jìn)行復(fù)制。當(dāng)某個(gè)對(duì)象在進(jìn)行了 15 次GC 后依舊存活,那這個(gè)對(duì)象就會(huì)進(jìn)入老年代。老年代因?yàn)槊看位厥盏膶?duì)象都會(huì)比較少,因此使用的是標(biāo)記整理算法。
垃圾回收器
講完了垃圾回收算法,我們?cè)倏聪吕厥掌鳎恳环N垃圾回收器都是不同時(shí)代的不同產(chǎn)物,都有其獨(dú)特性。
- Serial 垃圾收集器(單線程、復(fù)制算法)
- ParNew垃圾收集器(Serial+多線程)
- Parallel Scavenge 收集器(多線程復(fù)制算法、高效)
- SerialOld收集器(單線程標(biāo)記整理算法)
- ParallelOld收集器(多線程標(biāo)記整理算法)
- CMS收集器(多線程標(biāo)記清除算法)
- G1收集器
各個(gè)垃圾收集器的配合使用情況可以參考下圖,個(gè)人覺(jué)得對(duì)這么多的收集器沒(méi)有必要全部精通,可以注重關(guān)注一下 CMS 和 G1 就可以了。感興趣的小伙伴可以自己的研究一下。
本文題目:面試的時(shí)候按照這個(gè)套路回答JavaGC的相關(guān)問(wèn)題一定能過(guò)!
本文網(wǎng)址:http://m.fisionsoft.com.cn/article/cooeggp.html


咨詢
建站咨詢
