1. 為什么需要垃圾回收
如果不進(jìn)行垃圾回收棘催,內(nèi)存遲早被消耗空葛闷,因?yàn)槲覀冊(cè)诓粩喾峙鋬?nèi)存而沒(méi)有回收退盯,除非內(nèi)存無(wú)限大,我們可以任意分配不用回收辞色,但事實(shí)并非如此,所以砚哗,我們必須要進(jìn)行垃圾回收怔揩。
2. 哪些內(nèi)存需要回收
一些不再被使用的對(duì)象,比如我們?cè)贏ctivity琼稻、Fragment中的onDestroy()方法中把所有findViewById找到的控件置為null的這些對(duì)象吮螺,需要被回收。
3. 什么是JVM堆
3.1 JVM堆概念
JVM堆——是Java中對(duì)象的活動(dòng)空間范圍帕翻,代碼中的類里邊的對(duì)象是從 JVM堆中分配空間的鸠补,它里邊存儲(chǔ)著正在運(yùn)行的應(yīng)用程序中所有的對(duì)象,而這些對(duì)象的建立方式就是 new對(duì)象的那些操作嘀掸,當(dāng)對(duì)象不用了紫岩,是GC負(fù)責(zé)無(wú)用回收的對(duì)象
3.2 JVM堆
1>新域:存儲(chǔ)所有新生成的對(duì)象;
2>舊域:新域中的對(duì)象睬塌,經(jīng)過(guò)一定次數(shù)的GC循環(huán)后泉蝌,被移入舊域;
3>永久域:存儲(chǔ)類揩晴、方法梨与、對(duì)象,這個(gè)類是獨(dú)立的文狱,不包含在JVM堆中粥鞋,默認(rèn)為4M
4. JVM垃圾回收機(jī)制
java對(duì)內(nèi)存的釋放采取的是 —— 垃圾自動(dòng)回收機(jī)制,寫代碼時(shí)不用考慮 變量在不用的時(shí)候需要釋放內(nèi)存瞄崇,JVM(即就是java虛擬機(jī))會(huì)自動(dòng)判斷并收集垃圾呻粹,一般不會(huì)立即釋放它們的內(nèi)存空間,也可以手動(dòng)調(diào)用System.gc()苏研,表示強(qiáng)制立即回收垃圾等浊,即就是釋放內(nèi)存,注意摹蘑,系統(tǒng)并不會(huì)保證立即釋放內(nèi)存筹燕。
5. 什么是GC
GC(Garbage Collection)就是垃圾回收器,Java開(kāi)發(fā)人員不能像C衅鹿、C++開(kāi)發(fā)人員一樣使用指針來(lái)管理內(nèi)存撒踪,GC是JVM對(duì)內(nèi)存(其實(shí)就是對(duì)象)進(jìn)行管理的方式。程序員不用擔(dān)心內(nèi)存管理大渤,因?yàn)槔厥掌鲿?huì)自動(dòng)進(jìn)行管理制妄。GC使開(kāi)發(fā)人員擺脫了繁瑣的內(nèi)存管理工作,提高開(kāi)發(fā)效率泵三。
6. GC的基本原理
Java內(nèi)存管理耕捞,實(shí)際上就是對(duì) 對(duì)象的管理衔掸,包括對(duì)象的創(chuàng)建和釋放。創(chuàng)建就是new對(duì)象俺抽,釋放對(duì)象就是將其置為null敞映,讓程序不再能訪問(wèn)到這個(gè)對(duì)象,稱該對(duì)象為 "不可達(dá)的"磷斧,GC負(fù)責(zé)回收所有 "不可達(dá)的"對(duì)象的內(nèi)存空間振愿。
7. GC的目的
在堆中,找到無(wú)用的對(duì)象瞳抓,并把這些對(duì)象占用的空間收回讓其重新利用。
大多數(shù)垃圾回收算法思路都是一樣的:把所有對(duì)象組成一個(gè)集合伏恐,或者理解為樹狀結(jié)構(gòu)孩哑,從樹根開(kāi)始找,只要找到的都是活動(dòng)的對(duì)象翠桦,如果找不到横蜒,就說(shuō)明該對(duì)象已經(jīng)不再被使用了,就可以回收了销凑。
8. GC中回收算法
1>:標(biāo)記 - 清除算法
分為兩個(gè)階段丛晌,首先標(biāo)記出所有需要回收的對(duì)象,在標(biāo)記完成后統(tǒng)一回收所有被標(biāo)記的對(duì)象斗幼。
缺點(diǎn)是:標(biāo)記和清除效率都不高澎蛛,可能會(huì)產(chǎn)生很多碎片;
2>:標(biāo)記 - 整理算法
標(biāo)記整理與標(biāo)記清除算法過(guò)程一樣蜕窿,但是后邊不是簡(jiǎn)單的清除谋逻,而是讓所有存活的對(duì)象都向一端移動(dòng),然后清除邊界值以外的內(nèi)存桐经;
3>:復(fù)制算法
將可用內(nèi)存按容量劃分為相等的兩塊毁兆,每次只用其中一塊,當(dāng)這一塊用完阴挣,就將還存活的對(duì)象復(fù)制到另一塊上面气堕,然后把原始空間全部回收。高效畔咧、簡(jiǎn)單茎芭。
缺點(diǎn):將內(nèi)存縮小為原來(lái)一半;
4>:分代收集算法
新生代中誓沸,每次垃圾收集時(shí)都會(huì)有大批對(duì)象死去骗爆,只有少量存活,可以用復(fù)制算法蔽介,只需要付出少量存活對(duì)象的復(fù)制成本摘投,就可以完成收集煮寡;
老年代中,其存活率較高犀呼、沒(méi)有額外空間對(duì)它進(jìn)行分配擔(dān)保幸撕,就用 "標(biāo)記清除或者標(biāo)記整理"算法進(jìn)行回收。
9.建議
1.一般都是在Activity外臂、Fragment中的onDestroy()方法中把所有findViewById找到的對(duì)象全部置為null坐儿,在使用這種方式時(shí),需要注意一些復(fù)雜的對(duì)象圖宋光,比如:數(shù)組貌矿、隊(duì)列、樹罪佳、圖等逛漫,這些對(duì)象之間相互引用關(guān)系比較復(fù)雜,GC的回收效率也會(huì)比較低赘艳,如果程序允許酌毡,盡早將不用的 引用對(duì)象置為null,這樣可以加速GC的運(yùn)行速度蕾管;
- 盡量少用finalize()方法枷踏,finalize()方法是Java提供給程序員一個(gè)釋放對(duì)象或者釋放資源的機(jī)會(huì),但是它會(huì)加大GC的工作量掰曾,因此盡量少用finalize()方法來(lái)回收資源旭蠕;
- 如果需要使用 經(jīng)常使用的圖片,可以使用 soft(SoftReference)軟引用類型旷坦,它可以盡可能的將圖片保存在內(nèi)存中下梢,可供程序調(diào)用,不引起OOM塞蹭;
- 對(duì)于數(shù)組孽江、隊(duì)列、樹番电、圖等岗屏,這些數(shù)據(jù)結(jié)構(gòu)對(duì)于GC來(lái)說(shuō),回收更為復(fù)雜漱办,注意一些全局的變量这刷、靜態(tài)的變量,這些變量可能會(huì)引起內(nèi)存浪費(fèi)娩井;
- 當(dāng)程序有一定的等待時(shí)間暇屋,可以手動(dòng)執(zhí)行System.gc(),通知GC運(yùn)行洞辣。
9. 總結(jié)
1.JVM堆的大小決定了GC的運(yùn)行時(shí)間咐刨,如果JVM堆的大小超過(guò)一定限度昙衅,那么GC的運(yùn)行時(shí)間會(huì)很長(zhǎng);
2.對(duì)象的生存時(shí)間越長(zhǎng)定鸟,GC需要回收的時(shí)間也越長(zhǎng)而涉,影響回收速度;
3.如果GC運(yùn)行周期超過(guò)3-5秒联予,會(huì)很影響程序的運(yùn)行啼县,如果可以就需要減小JVM堆的大小沸久;
4.通常情況JVM堆的大小應(yīng)該為物理內(nèi)存的80%季眷;
- 應(yīng)用程序中,創(chuàng)建與釋放對(duì)象的速度決定了垃圾回收的頻率卷胯;
- 大多數(shù)對(duì)象都是短命的子刮,如果能讓這些對(duì)象的生存周期在GC的一次運(yùn)行周期內(nèi)就非常好了。