JVM垃圾回收機(jī)制
????提到Java垃圾回收機(jī)制就不得不提到一個方法:
????system.gc()用于調(diào)用垃圾收集器狮辽,在調(diào)用時垃圾收集器將運行以回收未使用的內(nèi)存空間纤壁,它將嘗試釋放被丟棄對象所占用的空間郑趁。
作為程序員有必要了解gc方法丛塌,這也是在面試中經(jīng)常會被問及的問題:
我們從三個方面來理解gc:
1.JVM如何確定哪些空間能被回收喧笔?
2.JVM會在什么時候進(jìn)行垃圾清除的動作?
3.JVM如何清除垃圾的悼瘾?
1.JVM如何確定哪些空間能被回收
通過兩個算法:
1.引用計數(shù)算法
簡單的來說就是判斷對象的引用數(shù)量囊榜。實現(xiàn)方式:給對象共添加一個引用計數(shù)器,每當(dāng)有引用對他進(jìn)行引用時亥宿,計數(shù)器的值就加1卸勺,當(dāng)引用失效,也就是不在執(zhí)行此對象是烫扼,他的計數(shù)器的值就減1曙求,若某一個對象的計數(shù)器的值為0,那么表示這個對象沒有人對他進(jìn)行引用,也就是意味著是一個失效的垃圾對象圆到,就會被gc進(jìn)行回收怎抛。但是這種簡單的算法在當(dāng)前的jvm中并沒有采用,原因是他并不能解決對象之間循環(huán)引用的問題芽淡。假設(shè)有A和B兩個對象之間互相引用,也就是說A對象中的一個屬性是B豆赏,B中的一個屬性時A,這種情況下由于他們的相互引用挣菲,從而是垃圾回收機(jī)制無法識別。
2.可達(dá)性分析算法
因為引用計數(shù)法的缺點有引入了可達(dá)性分析算法掷邦,通過判斷對象的引用鏈?zhǔn)欠窨蛇_(dá)來決定對象是否可以被回收白胀。可達(dá)性分析算法是從離散數(shù)學(xué)中的圖論引入的抚岗,程序把所有的引用關(guān)系看作一張圖或杠,通過一系列的名為GC Roots的對象作為起始點,從這些節(jié)點開始向下搜索宣蔚,搜索所走過的路徑稱為引用鏈向抢。當(dāng)一個對象到 GC Roots 沒有任何引用鏈相連(就是從 GC Roots 到這個對象不可達(dá))時,則證明此對象是不可用的胚委。
2.JVM會在什么時候進(jìn)行垃圾清除的動作
????會在cpu空閑的時候自動進(jìn)行回收挟鸠;
????在堆內(nèi)存存儲滿了之后;
????主動調(diào)用System.gc()后嘗試進(jìn)行回收(不一定成功)亩冬。
3.JVM如何清除垃圾的艘希?
通過四個算法:
標(biāo)記-清除算法:
????先標(biāo)記所有需要回收的對象,然后清除標(biāo)記的對象
缺點:會產(chǎn)生空間碎片硅急,資源浪費
復(fù)制算法
????將內(nèi)存分為兩塊覆享,當(dāng)使用的一塊滿了就將存活對象 復(fù)制到另一塊中,再將使用的那一塊清空
缺點:內(nèi)存縮小約為原來的一半
標(biāo)記-整理算法
????先標(biāo)記所有需要回收的對象营袜,然后清除標(biāo)記的對象撒顿,再將剩下的存活對象整理,避免了空間碎片的產(chǎn)生
分代收集算法
????分代收集算法是比較智能的垃圾回收算法连茧,也是現(xiàn)在JVM使用最多的算法核蘸,他本身其實并不算是一種算法,而是會在具體的場景上選擇上面三種方法來進(jìn)行垃圾回收
“代”指的是新生代啸驯、老年代客扎、永久代
新生代
????按8:1:1分為 eden、survivorl0罚斗、survivor1三個區(qū)域徙鱼。
一般情況下所有新生成的對象都存放于新生代。
在新生代中,每次垃圾收集時都發(fā)現(xiàn)有大批對象死去袱吆,只有少量存活厌衙,那就選用復(fù)制算法。只需要付出少量存活對象 的復(fù)制成本就可以完成收集绞绒。
老年代
????老年代中存放的一般都是生存周期比較長的對象婶希。
老年代中因為對象存活率高、沒有額外空間對他進(jìn)行分配擔(dān)保蓬衡,就必須用標(biāo)記-清除或者標(biāo)記-整理喻杈。
永久代
????主要用來存放靜態(tài)文件。
在jdk8的時候Java廢棄了永久代狰晚,同時提供了與永久代類似的叫做“元空間”的技術(shù)筒饰。元空間的本質(zhì)和永久代類似。不過元空間與永久代之間最大的區(qū)別在于:元空間并不在虛擬機(jī)中壁晒,而是使用本地內(nèi)存瓷们。也就是不局限于jvm可以使用系統(tǒng)的內(nèi)存。理論上取決于32位/64位系統(tǒng)可虛擬的內(nèi)存大小秒咐。