1.堆內存簡介
java
1.1什麼是堆內存? 算法
堆內存是java內存中的一種,它的做用是用於存儲java中的實例對象和數組,當咱們new一個對象或者建立一個數組的時候,就會在堆內存中開闢一段空間給它,用於存放。類加載器讀取了類文件後,須要把類、方法、常變量放到堆內存中,保存全部引用類型的真實信息,以方便執行器執行數組
1.2堆內存的特色spa
1.堆這塊區域是JVM中最大的,應用的對象和數據都是存在這個區域.線程
2.堆這塊區域也是線程共享的,也是 gc 主要的回收區.3d
3.一個JVM實例只存在一個堆內存,堆內存的大小是能夠調節的。orm
4.堆內存的存儲特色----先進先出,後進後出cdn
5.堆能夠動態地分配內存大小,生存期也沒必要事先告訴編譯器,由於它是在運行時動態分配內存的,但缺點是,因爲要在運行時動態分配內存,存取速度較慢對象
2.堆內存的組成部分blog
1.堆內存邏輯上由新生代 ( Young ),老年代 ( Old )和永久代(Perm)組成,其中新生代 ( Young )又被劃分爲:Eden、From Survivor(From區)和To Survivor(T區)三個區域
2.從JDK8開始,Metaspace(元空間)替代了永久代
3.注意事項(重要)
(1) 堆內存邏輯上由新生代 ( Young ),老年代 ( Old )和永久代(Perm)或者Metaspace(元空間)組成. (邏輯上:堆=新生+老年+永久或者元空間)
(2) 堆內存物理上由新生代 ( Young )和老年代 ( Old )組成,也就是堆內存的大小等於新生代的大小+老年代的大小(物理上:堆=新生+老年)
3.堆內存的空間比例分配
1.堆內存的空間分別分給了新生代和老年代,在默認狀況下新生代 ( Young ) 佔 1/3 的堆空間,老年代 ( Old ) 佔2/3 的堆空間
2.新生代 又被劃分爲:Eden、From Survivor(From區)和To Survivor(To區)三個區域,默認狀況下其中 Eden 區佔8/10 的新生代空間,from 和to 佔 1/10 的新生代空間.(Eden: from : to = 8 : 1 : 1)
4.新生代
新生代是類的誕生、成長、消亡的區域,一個類在這裏產生,應用,最後被垃圾回收器收集,結束生命;新生代又分爲兩部分:伊甸區(Eden)和兩個倖存者區(From區,To區)
4.1新生代的垃圾回收(MinorGC)
全部的類都是在伊甸區被new出來的,當伊甸園的空間用完時,程序又須要建立對象,JVM的垃圾回收器將對伊甸園區進行垃圾回收(MinorGC),將伊甸園區中的再也不被其餘對象所引用的對象進行銷燬。而後將伊甸園中的剩餘對象移動到倖存0區。若倖存0區也滿了,再對該區進行垃圾回收,而後移動到1 區。那若是1 區也滿了,再移動到養老區。若養老區也滿了,那麼這個時候將產生MajorGC(FullGC),進行養老區的內存清理。
4.1.1新生的垃圾回收過程(複製->清空->互換)
由於年輕代中的對象基本都是朝生夕死的(80%以上),因此在年輕代的垃圾回收算法使用的是複製算法
1.eden,From區複製到To區,年齡+1
首先,當Eden區滿的時候會觸發第一次GC,把還活着的對象拷貝到From區,當Eden區再次觸發GC的時候會掃描Eden區和From區域,對這兩個區域進行垃圾回收,通過此次回收後還存活的對象,則直接複製到To區域(若是有對象的年齡已經達到了老年的標準,則賦值到老年代區),同時把這些對象的年齡+1
2.清空,eden區,From區
而後,清空Eden和From區中的對象,也即複製以後有交換,誰空誰是to
3.To區和From區互換
最後,To區和From區互換,原To區成爲下一次GC時的From區。部分對象會在From區和To區域中複製來複制去,如此交換15次(次數能夠調節)最終若是仍是存活,就存入到老年代
4.2MinorGC
簡單一句說MinorGC的過程就是:複製->清空->互換,在新生代(年輕代)中使用的是MinorGC,這種GC採用的是複製算法;
4.3新生代(年輕代)的參數調節
5.年老代
主要接收由年輕代發送過來的對象,通常狀況下,通過了數次Minor GC 以後還會保存下來的對象纔會進入到老年代,當老年代內存不足時,將引起 "major GC」,即"Full GC
5.1注意事項
1.若養老區執行了FullGC以後發現依然沒法進行對象的保存,就會產生OOM異常「OutOfMemoryError」。
2.若是出現java.lang.OutOfMemoryError: Javaheap space異常,說明Java虛擬機的堆內存不夠,緣由有二
(1)Java虛擬機的堆內存設置不夠,能夠經過參數-Xms、-Xmx來調整。
(2)代碼中建立了大量大對象,而且長時間不能被垃圾收集器收集(存在被引用)
5.2Full GC
Full GC是發生在老年代的垃圾收集動做,老年代通常是由標記清除算法或者是標記清除算法與標記整理算法的混合實現,由於老年代裏面的對象幾乎個個都是在 Survivor 區域中存活過來的,因此,Full GC 發生的次數不會有 Minor GC 那麼頻繁,而且作一次 Full GC 要比進行一次 Minor GC 的時間更長
6.永久代(1.8以前)
永久代存儲區是一個常駐內存區域,用於存放JDK自身所攜帶的Class,Interface的元數據,也就是說它存儲的是運行環境必須的類信息,被裝載進此區域的數據是不會被垃圾回收器回收掉的,關閉JVM 纔會釋放此區域所佔用的內存
7.元空間(1.8)
在Java8中,永久代已經被移除,被一個稱爲元空間的區域所取代。元空間的本質和永久代相似。默認狀況下,元空間的大小僅受本地內存限制。類的元數據放入nativememory, 字符串池和類的靜態變量放入java 堆中,這樣能夠加載多少類的元數據就再也不由MaxPermSize控制, 而由系統的實際可用空間來控制。
元空間與永久代之間最大的區別在於:永久代帶使用的JVM的堆內存,可是java8之後的元空間並不在虛擬機中而是使用本機物理內存。