1. jvm怎么決定一個(gè)對(duì)象可以回收
①. 計(jì)數(shù)法
每個(gè)對(duì)象實(shí)例化的時(shí)候count 就加一, 刪除對(duì)象引用的時(shí)候減一测僵,這個(gè)方法的有點(diǎn)就是速度很快,但是這個(gè)方法有個(gè)問題。
比如:
class A{
B b;
}
class B{
A a;
}
A clazzA = new A();
B clazzB = new B();
clazzA.b=clazzB;
clazzB.a=clazzA;
//即使把clazzA 和clazzB都設(shè)置成null缅疟,他們的計(jì)數(shù)也不是0, 因?yàn)榫筒荒鼙换厥?clazzA=null;
clazzB=null;
②. Tracing
從gc root 對(duì)象開始查找引用遍愿,找到后繼續(xù)查找當(dāng)前引用的其他引用存淫,如此循環(huán)就構(gòu)成了一個(gè)圖,沒在圖中的就是下次要回收的潛在對(duì)象沼填。真正決定對(duì)象死亡需要2次標(biāo)記桅咆。
GC root對(duì)象:
- 虛擬機(jī)棧(棧幀中的本地變量表)中的引用的對(duì)象
- 方法區(qū)的類靜態(tài)屬性引用的對(duì)象
- 方法區(qū)的常量引用的對(duì)象
- 本地方法棧中JNI的應(yīng)用對(duì)象
2. GC 回收算法
①. Mark - Sweep
標(biāo)記-清除算法,首先標(biāo)記有reference的對(duì)象坞笙,沒有標(biāo)記的就是回收對(duì)象岩饼,需要清除。
缺點(diǎn):效率問題薛夜, 空間問題(產(chǎn)生好多不聯(lián)系的碎片)
②. Copying
把堆內(nèi)存分成2分籍茧,每次gc, 把一塊內(nèi)存的存活的對(duì)象復(fù)制到另一塊,然后清空這一塊內(nèi)存梯澜,這個(gè)可以利用的空間減少了一半寞冯。
③. Mark Compact
把標(biāo)記存活的對(duì)象,放到內(nèi)存開始的一端晚伙,然后清理邊界外的對(duì)象
④. Generational gc
按對(duì)象的存活周期把內(nèi)存分成幾塊吮龄,young generation, old generation, young generation 中把內(nèi)存分成較大的Eden空間, 和2個(gè)較小的Survivor空間,新生產(chǎn)的對(duì)象放到Eden空間咆疗,當(dāng)Eden 滿了的時(shí)候漓帚,GC把存活的對(duì)象移動(dòng)到第一個(gè)Survivor,并把Eden清空民傻,第二次GC的時(shí)候把第一個(gè)Eden胰默,Survivor空間的存活對(duì)象移動(dòng)到第二個(gè)Surivivor空間场斑, 并把其他清空,并把從第一個(gè)Survivor移動(dòng)的對(duì)象的age加1牵署, 下一次再把第二個(gè)Survivor空間的對(duì)象移動(dòng)到第一個(gè)Survivor漏隐,如此循環(huán),等age 到了一定值就會(huì)把對(duì)象移動(dòng)到old generation.