前言
在前面的文章中,介紹了JVM內(nèi)存模型分為:堆區(qū)、虛擬機(jī)棧曾雕、方法區(qū)、本地方法區(qū)和程序計(jì)數(shù)器助被,其中堆區(qū)是JVM中最大的一塊內(nèi)存區(qū)域剖张,在Java中的所有對(duì)象實(shí)例都保存在此區(qū)域,它能被所有線程共享揩环。
在Java中還有一個(gè)重要的機(jī)制:GC(垃圾收集器)搔弄,堆是GC管理的主要區(qū)域,本文會(huì)帶大家了解GC機(jī)制丰滑。
GC的簡(jiǎn)介
GC(Garbage Collection)垃圾收集機(jī)制是Java一個(gè)重要特性顾犹。不同于C/C++語(yǔ)言需要程序員自己管理內(nèi)存的回收,而且這樣做往往容易出錯(cuò),導(dǎo)致內(nèi)存泄漏等嚴(yán)重問(wèn)題炫刷。
Java程序員不用編寫(xiě)回收內(nèi)存的代碼擎宝,因?yàn)镴ava有GC機(jī)制,它是一個(gè)特殊的后臺(tái)線程浑玛,該線程對(duì)JVM中的內(nèi)存進(jìn)行標(biāo)記认臊,并確定哪些需要回收,再通過(guò)一定的回收策略自動(dòng)回收內(nèi)存锄奢,它在后臺(tái)一直運(yùn)行失晴,保證JVM不會(huì)出現(xiàn)內(nèi)存溢出的問(wèn)題。
對(duì)象回收的算法
那么GC是如何判斷某個(gè)對(duì)象的內(nèi)存需要回收呢拘央?GC需要判斷該對(duì)象已死涂屁,也就是不再被調(diào)用,如何判斷對(duì)象不再被調(diào)用呢灰伟?
這里有兩種算法:
引用計(jì)數(shù)算法
可達(dá)性分析算法
引用計(jì)數(shù)算法
該算法給每個(gè)對(duì)象分配一個(gè)計(jì)數(shù)器拆又,當(dāng)有引用指向這個(gè)對(duì)象時(shí),計(jì)數(shù)器加1栏账,當(dāng)指向該對(duì)象的引用失效時(shí)帖族,計(jì)數(shù)器減一。最后如果該對(duì)象的計(jì)數(shù)器為0時(shí)挡爵,java垃圾回收器會(huì)認(rèn)為該對(duì)象是可回收的竖般。
優(yōu)點(diǎn):
1、實(shí)時(shí)性高茶鹃,只要對(duì)象計(jì)數(shù)器為0就進(jìn)行回收涣雕,不用等到內(nèi)存不足的時(shí)候。
2闭翩、在垃圾回收過(guò)程中挣郭,應(yīng)用無(wú)需掛起。
3疗韵、更新對(duì)象的計(jì)數(shù)器時(shí)兑障,只是影響到該對(duì)象,不會(huì)掃描全部對(duì)象蕉汪。
缺點(diǎn):
每次引用對(duì)象時(shí)流译,都會(huì)更新計(jì)數(shù)器,有時(shí)間消耗
不能解決循環(huán)引用問(wèn)題
那什么是循環(huán)引用問(wèn)題呢?我們看下面這段代碼:
class ClassA{
ClassB b;
}
class ClassB{
ClassA a;
}
public static void main(String[] args){
ClassA a = new ClassA();
ClassB b = new ClassB();
a.b = b;
b.a = a;
a = null;
b = null;
}
上面的a肤无、b兩個(gè)對(duì)象雖然都賦值為null先蒋,但是都不能回收,因?yàn)榇嬖谘h(huán)引用宛渐,它們的計(jì)數(shù)器不為0.
可達(dá)性分析算法
該算法通過(guò)一種被稱作“GC Root”的對(duì)象作為起始點(diǎn)竞漾,從這些節(jié)點(diǎn)開(kāi)始向下搜索眯搭,搜索所走過(guò)的路徑稱為引用鏈,當(dāng)一個(gè)對(duì)象到GC Roots沒(méi)有任何引用鏈相連時(shí)业岁,則證明此對(duì)象時(shí)不可用的鳞仙。
如下圖:
在Java語(yǔ)言中,可作為GC Roots對(duì)象包括下面幾種:
1)虛擬機(jī)棧中引用的對(duì)象
2)方法區(qū)中類靜態(tài)屬性引用的對(duì)象
3)方法區(qū)常量池中引用的對(duì)象
3)本地方法棧中JNI引用的對(duì)象
再回頭看前面這段代碼笔时,雖然a和b對(duì)象的引用計(jì)數(shù)都不為0棍好,但是它們作為GC Root對(duì)象,最后都賦值為null允耿,導(dǎo)致引用不可達(dá)借笙,這樣兩個(gè)對(duì)象都是可以被回收的。
總結(jié)
本文我們學(xué)習(xí)了JVM中的垃圾收集(GC)機(jī)制较锡,GC是一個(gè)在后臺(tái)持續(xù)運(yùn)行的線程业稼,幫助我們回收J(rèn)VM堆中的對(duì)象內(nèi)存,保證JVM不會(huì)內(nèi)存溢出蚂蕴。
如何判斷對(duì)象內(nèi)存需要回收低散,有兩個(gè)算法:引用計(jì)數(shù)算法和可達(dá)性分析算法。
引用計(jì)數(shù)算法通過(guò)判斷對(duì)象的引用計(jì)數(shù)為0骡楼,就標(biāo)記該對(duì)象內(nèi)存可以回收熔号,但是不能很好的解決循環(huán)引用問(wèn)題;可達(dá)性分析算法通過(guò)GC Root向下搜索鸟整,如果引用鏈相連則對(duì)象可達(dá)引镊,否則標(biāo)記對(duì)象不可達(dá),可以進(jìn)行回收吃嘿,這種算法能很好解決對(duì)象循環(huán)引用問(wèn)題祠乃。