GC原理被盈,性能調(diào)優(yōu)
通過IDEA 運(yùn)行JAVA代碼,java代碼執(zhí)行過程
- 編譯源代碼
- 編譯java文件生成字節(jié)碼文件
- JVM 中的類加載器袜瞬,加載字節(jié)碼文件
- JVM 中的執(zhí)行引擎找到入口方法main(),執(zhí)行其中的方法
JVM 垃圾回收
JVM回收原理身堡,把對象分為年青代、年老代汞扎,持久代,對不同生命周期的對象使用不同的算法景鼠。(基于對對象生命周期分析)
通常我們說的JVM內(nèi)存回收總是在指堆內(nèi)存回收痹扇,確實(shí)只有堆中的內(nèi)容是動態(tài)生氣分配的鲫构,所以以上對象的年青代和年老代都是指的JVM的Heap空間, 而持久代則是之前提到的MethodArea芬迄,不屬于Head禀梳。
- GC 的基本原理:講內(nèi)存中不再被使用的對象進(jìn)行回收,GC中用于回收的方法稱為收集器肠骆,由于GC需要消耗一些資源和時(shí)間算途,Java在對對象的生命周期特征進(jìn)行分析后,按照新生代蚀腿,舊生代的方式來對對象進(jìn)行收集嘴瓤,以盡可能的縮短GC對應(yīng)用造成的暫停
1)對新生代的對象的收集稱為minor GC;
2)對舊生代的對象的收集稱為Full GC莉钙;
3)程序中主動調(diào)用System.gc()強(qiáng)制執(zhí)行的GC為Full GC
不同的對象引用類型廓脆,GC會采用不同的方法進(jìn)行回收,JVM對象的引用分為了四種類型: - 強(qiáng)引用:默認(rèn)情況下磁玉,對象采用的均為強(qiáng)引用(這個(gè)對象的實(shí)例沒有其他對象引用停忿,GC時(shí)才會被銷毀回收)
- 軟引用:軟引用是Java中提供的一種比較合適與緩存場景的應(yīng)用(只有在內(nèi)存不夠的用的情況下才會被回收)
- 虛引用:由于虛引用只是用來得知對象是否被GC
JVM的對象分配規(guī)則
對象優(yōu)先分配在Eden區(qū)【使用空間】,如果Eden區(qū)沒有足夠的空間時(shí)席赂,虛擬機(jī)執(zhí)行一次Minor GC【垃圾回收】。
大對象直接進(jìn)入老年代(大對象是指需要大量連續(xù)內(nèi)存空間的對象)时迫。這樣做的目的是避免在Eden區(qū)和兩個(gè)Survivor區(qū)之間發(fā)生大量的內(nèi)存拷貝(新生代采用復(fù)制算法收集內(nèi)存)颅停。
長期存活的對象進(jìn)入老年代。虛擬機(jī)為每個(gè)對象定義了一個(gè)年齡計(jì)數(shù)器掠拳,如果對象經(jīng)過了1次Minor GC(年輕代收集)那么對象會進(jìn)入Survivor區(qū)癞揉,之后每經(jīng)過一次Minor GC那么對象的年齡加1,直到達(dá)到閥值對象進(jìn)入老年區(qū)。
動態(tài)判斷對象的年齡烧董。如果Survivor區(qū)中相同年齡的所有對象大小的總和大于Survivor空間的一半毁靶,年齡大于或等于該年齡的對象可以直接進(jìn)入老年代。
空間分配擔(dān)保逊移。每次進(jìn)行Minor GC時(shí)预吆,JVM會計(jì)算Survivor區(qū)移至老年區(qū)的對象的平均大小,如果這個(gè)值大于老年區(qū)的剩余值大小則進(jìn)行一次Full GC胳泉,如果小于檢查HandlePromotionFailure設(shè)置拐叉,如果true則只進(jìn)行Monitor GC,如果false則進(jìn)行Full GC。
簡要概括如下
- 對象先在Eden區(qū)扇商,Eden區(qū)空間不夠時(shí)進(jìn)行新生代GC
- 大對象和長期存活的對象進(jìn)入老年代
- JVM為每個(gè)對象設(shè)置了計(jì)數(shù)器凤瘦,經(jīng)過1次新生代GC則進(jìn)入幸存者區(qū),達(dá)到年齡閾值則進(jìn)入老年區(qū)
- 幸存者區(qū)中年齡一致的對象所占內(nèi)存大小案铺,大于幸存者區(qū)空間一半時(shí)蔬芥,則大于等于此年齡的對象全部進(jìn)入老年代
- 老年代GC通常伴隨著一次新生代GC,但不絕對
YOUNG(年輕代)
年輕代分為三個(gè)區(qū)控汉,一個(gè)Eden區(qū)笔诵,兩個(gè)Survivor區(qū)。大部分對象在Eden去中生成姑子。當(dāng)Eden區(qū)滿時(shí)乎婿,還存活的對象將被復(fù)制到Survivor區(qū),當(dāng)這個(gè)Survivor區(qū)也滿的時(shí)候街佑,從第一個(gè)Survivor的兩個(gè)區(qū)復(fù)制過來的并且此時(shí)還存活的對象谢翎,將被復(fù)制到年老區(qū)(Survivor的兩個(gè)區(qū)是對稱的,沒有先后關(guān)系沐旨,所以同一個(gè)區(qū)可能同時(shí)存在從Eden復(fù)制過來的對象森逮,和從前一個(gè)Survivor復(fù)制過來的對象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過去的對象希俩,并且Survivor區(qū)總有一個(gè)是空的)吊宋。
Tenured 年老代
年老代存放從年輕代存活的對象,一般來說年老代存放的都是生命周期較長的對象颜武。
持久代Perm
用于存放靜態(tài)文件璃搜,如今Java類,方法等鳞上,持久代對垃圾回收沒有明顯的影響这吻,但是有些應(yīng)用可能動態(tài)生成活調(diào)用一些class,列如Hibernate等篙议,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程新增的類唾糯。持久代大小通過-XX:MaxPermSize 進(jìn)行設(shè)置怠硼。