GC原理,性能調(diào)優(yōu)
通過(guò)IDEA 運(yùn)行JAVA代碼,java代碼執(zhí)行過(guò)程
- 編譯源代碼
- 編譯java文件生成字節(jié)碼文件
- JVM 中的類加載器,加載字節(jié)碼文件
- JVM 中的執(zhí)行引擎找到入口方法main(),執(zhí)行其中的方法
JVM 垃圾回收
JVM回收原理,把對(duì)象分為年青代、年老代,持久代,對(duì)不同生命周期的對(duì)象使用不同的算法。(基于對(duì)對(duì)象生命周期分析)
通常我們說(shuō)的JVM內(nèi)存回收總是在指堆內(nèi)存回收,確實(shí)只有堆中的內(nèi)容是動(dòng)態(tài)生氣分配的,所以以上對(duì)象的年青代和年老代都是指的JVM的Heap空間, 而持久代則是之前提到的MethodArea,不屬于Head。
- GC 的基本原理:講內(nèi)存中不再被使用的對(duì)象進(jìn)行回收,GC中用于回收的方法稱為收集器,由于GC需要消耗一些資源和時(shí)間,Java在對(duì)對(duì)象的生命周期特征進(jìn)行分析后,按照新生代,舊生代的方式來(lái)對(duì)對(duì)象進(jìn)行收集,以盡可能的縮短GC對(duì)應(yīng)用造成的暫停
1)對(duì)新生代的對(duì)象的收集稱為minor GC;
2)對(duì)舊生代的對(duì)象的收集稱為Full GC;
3)程序中主動(dòng)調(diào)用System.gc()強(qiáng)制執(zhí)行的GC為Full GC
不同的對(duì)象引用類型,GC會(huì)采用不同的方法進(jìn)行回收,JVM對(duì)象的引用分為了四種類型: - 強(qiáng)引用:默認(rèn)情況下,對(duì)象采用的均為強(qiáng)引用(這個(gè)對(duì)象的實(shí)例沒(méi)有其他對(duì)象引用,GC時(shí)才會(huì)被銷毀回收)
- 軟引用:軟引用是Java中提供的一種比較合適與緩存場(chǎng)景的應(yīng)用(只有在內(nèi)存不夠的用的情況下才會(huì)被回收)
- 虛引用:由于虛引用只是用來(lái)得知對(duì)象是否被GC
JVM的對(duì)象分配規(guī)則
對(duì)象優(yōu)先分配在Eden區(qū)【使用空間】,如果Eden區(qū)沒(méi)有足夠的空間時(shí),虛擬機(jī)執(zhí)行一次Minor GC【垃圾回收】。
大對(duì)象直接進(jìn)入老年代(大對(duì)象是指需要大量連續(xù)內(nèi)存空間的對(duì)象)。這樣做的目的是避免在Eden區(qū)和兩個(gè)Survivor區(qū)之間發(fā)生大量的內(nèi)存拷貝(新生代采用復(fù)制算法收集內(nèi)存)。
長(zhǎng)期存活的對(duì)象進(jìn)入老年代。虛擬機(jī)為每個(gè)對(duì)象定義了一個(gè)年齡計(jì)數(shù)器,如果對(duì)象經(jīng)過(guò)了1次Minor GC(年輕代收集)那么對(duì)象會(huì)進(jìn)入Survivor區(qū),之后每經(jīng)過(guò)一次Minor GC那么對(duì)象的年齡加1,直到達(dá)到閥值對(duì)象進(jìn)入老年區(qū)。
動(dòng)態(tài)判斷對(duì)象的年齡。如果Survivor區(qū)中相同年齡的所有對(duì)象大小的總和大于Survivor空間的一半,年齡大于或等于該年齡的對(duì)象可以直接進(jìn)入老年代。
空間分配擔(dān)保。每次進(jìn)行Minor GC時(shí),JVM會(huì)計(jì)算Survivor區(qū)移至老年區(qū)的對(duì)象的平均大小,如果這個(gè)值大于老年區(qū)的剩余值大小則進(jìn)行一次Full GC,如果小于檢查HandlePromotionFailure設(shè)置,如果true則只進(jìn)行Monitor GC,如果false則進(jìn)行Full GC。
簡(jiǎn)要概括如下
- 對(duì)象先在Eden區(qū),Eden區(qū)空間不夠時(shí)進(jìn)行新生代GC
- 大對(duì)象和長(zhǎng)期存活的對(duì)象進(jìn)入老年代
- JVM為每個(gè)對(duì)象設(shè)置了計(jì)數(shù)器,經(jīng)過(guò)1次新生代GC則進(jìn)入幸存者區(qū),達(dá)到年齡閾值則進(jìn)入老年區(qū)
- 幸存者區(qū)中年齡一致的對(duì)象所占內(nèi)存大小,大于幸存者區(qū)空間一半時(shí),則大于等于此年齡的對(duì)象全部進(jìn)入老年代
- 老年代GC通常伴隨著一次新生代GC,但不絕對(duì)
YOUNG(年輕代)
年輕代分為三個(gè)區(qū),一個(gè)Eden區(qū),兩個(gè)Survivor區(qū)。大部分對(duì)象在Eden去中生成。當(dāng)Eden區(qū)滿時(shí),還存活的對(duì)象將被復(fù)制到Survivor區(qū),當(dāng)這個(gè)Survivor區(qū)也滿的時(shí)候,從第一個(gè)Survivor的兩個(gè)區(qū)復(fù)制過(guò)來(lái)的并且此時(shí)還存活的對(duì)象,將被復(fù)制到年老區(qū)(Survivor的兩個(gè)區(qū)是對(duì)稱的,沒(méi)有先后關(guān)系,所以同一個(gè)區(qū)可能同時(shí)存在從Eden復(fù)制過(guò)來(lái)的對(duì)象,和從前一個(gè)Survivor復(fù)制過(guò)來(lái)的對(duì)象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過(guò)去的對(duì)象,并且Survivor區(qū)總有一個(gè)是空的)。
Tenured 年老代
年老代存放從年輕代存活的對(duì)象,一般來(lái)說(shuō)年老代存放的都是生命周期較長(zhǎng)的對(duì)象。
持久代Perm
用于存放靜態(tài)文件,如今Java類,方法等,持久代對(duì)垃圾回收沒(méi)有明顯的影響,但是有些應(yīng)用可能動(dòng)態(tài)生成活調(diào)用一些class,列如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來(lái)存放這些運(yùn)行過(guò)程新增的類。持久代大小通過(guò)-XX:MaxPermSize 進(jìn)行設(shè)置。