GC 年轻代 老年代 持久代
轉(zhuǎn)載自:http://www.cnblogs.com/yaoyuan23/p/5587548.html
?
?虛擬機(jī)中的共劃分為三個(gè)代:年輕代(Young Generation)、老年代(Old Generation)和持久代(Permanent Generation)。其中持久代主要存放的是Java類的類信息,與垃圾收集要收集的Java對(duì)象關(guān)系不大。年輕代和年老代的劃分是對(duì)垃圾收集影響比較大的。
? ? ?
年輕代:
所有新生成的對(duì)象首先都是放在年輕代的。年輕代的目標(biāo)就是盡可能快速的收集掉那些生命周期短的對(duì)象。年輕代分三個(gè)區(qū)。一個(gè)Eden區(qū),兩個(gè)Survivor區(qū)(一般而言)。大部分對(duì)象在Eden區(qū)中生成。當(dāng)Eden區(qū)滿時(shí),還存活的對(duì)象將被復(fù)制到Survivor區(qū)(兩個(gè)中的一個(gè)),當(dāng)這個(gè)Survivor區(qū)滿時(shí),此區(qū)的存活對(duì)象將被復(fù)制到另外一個(gè)Survivor區(qū),當(dāng)這個(gè)Survivor去也滿了的時(shí)候,從第一個(gè)Survivor區(qū)復(fù)制過來的并且此時(shí)還存活的對(duì)象,將被復(fù)制“年老區(qū)(Tenured)”。需要注意,Survivor的兩個(gè)區(qū)是對(duì)稱的,沒先后關(guān)系,所以同一個(gè)區(qū)中可能同時(shí)存在從Eden復(fù)制過來 對(duì)象,和從前一個(gè)Survivor復(fù)制過來的對(duì)象,而復(fù)制到年老區(qū)的只有從第一個(gè)Survivor去過來的對(duì)象。而且,Survivor區(qū)總有一個(gè)是空的。同時(shí),根據(jù)程序需要,Survivor區(qū)是可以配置為多個(gè)的(多于兩個(gè)),這樣可以增加對(duì)象在年輕代中的存在時(shí)間,減少被放到年老代的可能。
年老代:
在年輕代中經(jīng)歷了N次垃圾回收后仍然存活的對(duì)象,就會(huì)被放到年老代中。因此,可以認(rèn)為年老代中存放的都是一些生命周期較長(zhǎng)的對(duì)象。
持久代:
用于存放靜態(tài)文件,如今Java類、方法等。持久代對(duì)垃圾回收沒有顯著影響,但是有些應(yīng)用可能動(dòng)態(tài)生成或者調(diào)用一些class,例如Hibernate等,在這種時(shí)候需要設(shè)置一個(gè)比較大的持久代空間來存放這些運(yùn)行過程中新增的類。持久代大小通過-XX:MaxPermSize=<N>進(jìn)行設(shè)置。
?
Scavenge GC
一般情況下,當(dāng)新對(duì)象生成,并且在Eden申請(qǐng)空間失敗時(shí),就會(huì)觸發(fā)Scavenge GC,對(duì)Eden區(qū)域進(jìn)行GC,清除非存活對(duì)象,并且把尚且存活的對(duì)象移動(dòng)到Survivor區(qū)。然后整理Survivor的兩個(gè)區(qū)。這種方式的GC是對(duì)年輕代的Eden區(qū)進(jìn)行,不會(huì)影響到年老代。因?yàn)榇蟛糠謱?duì)象都是從Eden區(qū)開始的,同時(shí)Eden區(qū)不會(huì)分配的很大,所以Eden區(qū)的GC會(huì)頻繁進(jìn)行。因而,一般在這里需要使用速度快、效率高的算法,使Eden去能盡快空閑出來。
Full GC
對(duì)整個(gè)堆進(jìn)行整理,包括Young、Tenured和Perm。Full GC因?yàn)樾枰獙?duì)整個(gè)對(duì)進(jìn)行回收,所以比Scavenge GC要慢,因此應(yīng)該盡可能減少Full GC的次數(shù)。在對(duì)JVM調(diào)優(yōu)的過程中,很大一部分工作就是對(duì)于FullGC的調(diào)節(jié)。有如下原因可能導(dǎo)致Full GC:
·?年老代(Tenured)被寫滿
·?持久代(Perm)被寫滿
·?System.gc()被顯示調(diào)用
·上一次GC之后Heap的各域分配策略動(dòng)態(tài)變化
?
?
看一段日志:
? ? ? ?
at?java.util.concurrent.ThreadPoolExecutor$Worker.runTask (ThreadPoolExecutor.java:886) at?java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:908) at?java.lang.Thread.run(Thread.java:662) Exception?in?thread?"http-bio-17788-exec-74"? java.lang.OutOfMemoryError:?PermGen?space Exception?in?thread?"http-bio-17788-exec-75"? java.lang.OutOfMemoryError:?PermGen?space Exception?in?thread?"http-bio-17788-exec-76"? java.lang.OutOfMemoryError:?PermGen?space? ? ?明顯可以看出是老年代的內(nèi)存溢出,說明在容器下的靜態(tài)文件過多,比如編譯的字節(jié)碼,jsp編譯成servlet,或者jar包。
? ? ?解決此問題,修改jvm的參數(shù)?permsize即可,permsize初始默認(rèn)為64m。
?
? ?jvm內(nèi)存參數(shù)
-vmargs -Xms128M -Xmx512M -XX:PermSize=64M -XX:MaxPermSize=128M
-vmargs 說明后面是VM的參數(shù),所以后面的其實(shí)都是JVM的參數(shù)了
-Xms128m JVM初始分配的堆內(nèi)存
-Xmx512m JVM最大允許分配的堆內(nèi)存,按需分配
-XX:PermSize=64M JVM初始分配的非堆內(nèi)存
-XX:MaxPermSize=128M JVM最大允許分配的非堆內(nèi)存,按需分配
?
堆(Heap)和非堆(Non-heap)內(nèi)存
?按照官方的說法:“Java 虛擬機(jī)具有一個(gè)堆,堆是運(yùn)行時(shí)數(shù)據(jù)區(qū)域,所有類實(shí)例和數(shù)組的內(nèi)存均從此處分配。堆是在 Java 虛擬機(jī)啟動(dòng)時(shí)創(chuàng)建的?!薄霸贘VM中堆之外的內(nèi)存稱為非堆內(nèi)存(Non-heap memory)”。
?可以看出JVM主要管理兩種類型的內(nèi)存:堆和非堆。簡(jiǎn)單來說堆就是Java代碼可及的內(nèi)存,是留給開發(fā)人員使用的;非堆就是JVM留給自己用的,
轉(zhuǎn)載于:https://www.cnblogs.com/rzqz/p/7284995.html
總結(jié)
以上是生活随笔為你收集整理的GC 年轻代 老年代 持久代的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MyBatis学习存档(4)——进行CR
- 下一篇: c# Json格式