上文中,在介紹運行時數據區域中的 JAVA 堆時,提到了 JVM 中的堆,通常分爲三大部分:新生代、老年代、永久代,本文將進一步瞭解運行時的內存分配狀況。java
1.新生代
主要用來存放新生(new)的對象。通常佔據堆的 1/3 空間。因爲頻繁建立對象,因此新生代會頻繁的觸發 MinorGC 進行垃圾回收。算法
新生代又分爲 Eden(伊甸園)、SurvivorFrom、SurvivorTo三個區。安全
當Eden區內存不夠的時候就會觸發MinorGC,對新生代區進行一次垃圾回收,當觸發GC後,JVM會將Eden和其中一個Survivor的對象所有複製到另一個Survivor中(例如從from 到 to),即採用的複製算法(垃圾回收算法中的一種),在複製過程當中,若是對象達到了老生代的要求就會被複制到老生代,複製到Servivor的每一個對象的年齡加一,而後清空Eden和以前的Servivor區域。從這裏就能夠看出在任意時刻必定會存在一個Survivor區域處於空閒狀態。微信
2.老年代:
主要存放應用程序中生命週期長的內存對象。老年代的對象比較穩定,因此MajorGC不會頻繁執行。app
在進行MajorGC前通常都先進行了一次MinorGC,使得有新生代的對象晉身入老年代,致使空間不夠用時才觸發。當沒法找到足夠大的連續空間分配給新建立的較大對象時也會提早觸發一次MajorGC進行垃圾回收騰出空間。jvm
MajorGC採用標記—清除算法(垃圾回收算法中的一種):首先掃描一次全部老年代,標記出存活的對象,而後回收沒有標記的對象。MajorGC的耗時比較長,由於要掃描再回收。MajorGC會產生內存碎片,爲了減小內存損耗,咱們通常須要進行合併或者標記出來方便下次直接分配。 spa
當老年代也滿了裝不下的時候,就會拋出OOM(Out of Memory)異常。orm
3.永久代
在Java8中,永久代已經被移除,被一個稱爲「元數據區」(元空間)的區域所取代。元空間的本質和永久代相似,都是對JVM規範中方法區的實現。不過元空間與永久代之間最大的區別在於:元空間並不在虛擬機中,而是使用本地內存。所以,默認狀況下,元空間的大小僅受本地內存限制。類的元數據放入 Native memory, 字符串池和類的靜態變量放入Java堆中. 這樣能夠加載多少類的元數據就再也不由MaxPermSize控制, 而由系統的實際可用空間來控制.對象
前邊巴拉巴拉講了一堆,終於到了總結部分,首先咱們瞭解到堆內存主要分爲三部分:新生代、老年代、永久代。blog
上邊提到的垃圾回收算法有,複製算法、標記-清除算法,未提到的還有 標記-整理算法、分代收集算法(下一篇講解算法部分),當前商業虛擬機(如HotSpot)的垃圾收集都採用 分代收集算法,接下來將以 分代收集算法 描述對象的從建立到 GC 的過程。
一、一我的(對象)出來(new 出來)後會在Eden Space(伊甸園)無憂無慮的生活,直到GC到來打破了他們平靜的生活。GC會逐一問清楚每一個對象的狀況,有沒有錢(此對象的引用)啊,由於GC想賺錢呀,有錢的才能夠敲詐嘛。而後富人就會進入Survivor Space(倖存者區),窮人的就直接kill掉。
二、並非進入Survivor Space(倖存者區)後就保證人身是安全的,但至少能夠活段時間。GC會按期(能夠自定義)會對這些人進行敲詐,億萬富翁每次都給錢,GC很滿意,就讓其進入了Genured Gen(養老區)。萬元戶經不住幾回敲詐就沒錢了,GC看沒有啥價值啦,就直接kill掉了。
三、進入到養老區的人基本就能夠保證人身安全啦,可是億萬富豪有的也會揮霍成窮光蛋,只要錢沒了,GC仍是kill掉。
分區的目的:新生區因爲對象產生的比較多而且大都是朝生夕滅的,因此直接採用標記-清理算法。而養老區生命力很強,則採用複製算法,針對不一樣狀況使用不一樣算法。
描述參考:https://lhc1986.iteye.com/blog/1421832
若是文章有錯的地方歡迎指正,你們互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:niceyoo