【JAVA】【JVM篇】【垃圾回收機(jī)制】
1. 概述:
垃圾收集GC(Garbage Collection)是Java語(yǔ)言的核心技術(shù)之一恃泪, 在Java中谱仪,程序員不需要去關(guān)心內(nèi)存動(dòng)態(tài)分配和垃圾回收的問(wèn)題,這一切都交給了JVM來(lái)處理。
2.什么樣的數(shù)據(jù)才是垃圾?
這個(gè)問(wèn)題其實(shí)很簡(jiǎn)單,對(duì)于Java對(duì)象來(lái)講井厌,如果說(shuō)這個(gè)對(duì)象沒(méi)有被其他對(duì)象所引用該對(duì)象就是無(wú)用的,此對(duì)象就被稱為垃圾致讥,其占用的內(nèi)存也就要被銷(xiāo)毀仅仆。如果不對(duì)垃圾數(shù)據(jù)進(jìn)行刪除很容易會(huì)造成內(nèi)存溢出。
3.回顧一下JVM模型再繼續(xù)往下談
垃圾回收機(jī)制主要針對(duì)的是堆內(nèi)存的垃圾數(shù)據(jù)進(jìn)行刪除垢袱,從而回收內(nèi)存墓拜。
1)新生代(Young Generation)
新生代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象,一般情況下请契,所有新生成的對(duì)象首先都是放在新生代的咳榜。新生代內(nèi)存按照 8:1:1 的比例分為一個(gè)eden區(qū)和兩個(gè)survivor(survivor0,survivor1)區(qū)爽锥,大部分對(duì)象在Eden區(qū)中生成涌韩。在進(jìn)行垃圾回收時(shí),先將eden區(qū)存活對(duì)象復(fù)制到survivor0區(qū)氯夷,然后清空eden區(qū)臣樱,當(dāng)這個(gè)survivor0區(qū)也滿了時(shí),則將eden區(qū)和survivor0區(qū)存活對(duì)象復(fù)制到survivor1區(qū)腮考,然后清空eden和這個(gè)survivor0區(qū)雇毫,此時(shí)survivor0區(qū)是空的,然后交換survivor0區(qū)和survivor1區(qū)的角色(即下次垃圾回收時(shí)會(huì)掃描Eden區(qū)和survivor1區(qū))踩蔚,即保持survivor0區(qū)為空棚放,如此往復(fù)。特別地馅闽,當(dāng)survivor1區(qū)也不足以存放eden區(qū)和survivor0區(qū)的存活對(duì)象時(shí)飘蚯,就將存活對(duì)象直接存放到老年代馍迄。如果老年代也滿了,就會(huì)觸發(fā)一次FullGC孝冒,也就是新生代柬姚、老年代都進(jìn)行回收。注意庄涡,新生代發(fā)生的GC也叫做MinorGC,MinorGC發(fā)生頻率比較高搬设,不一定等 Eden區(qū)滿了才觸發(fā)穴店。
2)老年代(Old Generation)
老年代存放的都是一些生命周期較長(zhǎng)的對(duì)象,就像上面所敘述的那樣拿穴,在新生代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象就會(huì)被放到老年代中泣洞。此外,老年代的內(nèi)存也比新生代大很多(大概比例是1:2)默色,當(dāng)老年代滿時(shí)會(huì)觸發(fā)Major GC(Full GC)球凰,老年代對(duì)象存活時(shí)間比較長(zhǎng),因此FullGC發(fā)生的頻率比較低腿宰。
3)永久代(Permanent Generation)
永久代主要用于存放靜態(tài)文件呕诉,如Java類(lèi)信息、常量池吃度、靜態(tài)變量等甩挫。永久代對(duì)垃圾回收沒(méi)有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class椿每,例如使用反射伊者、動(dòng)態(tài)代理、CGLib等bytecode框架時(shí)间护,在這種時(shí)候需要設(shè)置一個(gè)比較大的永久代空間來(lái)存放這些運(yùn)行過(guò)程中新增的類(lèi)亦渗。
JDK1.8之后永久代被刪除,常量池汁尺、靜態(tài)變量放入堆中法精,Java類(lèi)信息放在元空間中。
4.垃圾回收的兩種類(lèi)型
(a) Minor GC:對(duì)新生代進(jìn)行回收均函,不會(huì)影響到年老代亿虽。因?yàn)樾律?Java 對(duì)象大多死亡頻繁,所以 Minor GC 非常頻繁苞也,一般在這里使用速度快洛勉、效率高的算法,使垃圾回收能盡快完成如迟。
(b)Full GC:也叫 Major GC收毫,對(duì)整個(gè)堆進(jìn)行回收攻走,包括新生代和老年代。由于Full GC需要對(duì)整個(gè)堆進(jìn)行回收此再,所以比Minor GC要慢昔搂,因此應(yīng)該盡可能減少Full GC的次數(shù),導(dǎo)致Full GC的原因包括:老年代被寫(xiě)滿输拇、永久代(Perm)被寫(xiě)滿和System.gc()被顯式調(diào)用等摘符。