JVM中堆的介紹


一.堆的概述

   一個JVM實例只有一個堆內存,堆也是Java內存管理的核心區域,堆在JVM啟動的時候創建,其空間大小也被創建,是JVM中最大的一塊內存空間,所有線程共享Java堆,物理上不連續的邏輯上連續的內存空間,幾乎所有的實例都在這里分配內存,在方法結束后,堆中的對象不會馬上刪除,僅僅在垃圾收集的時候被刪除,堆是GC(垃圾收集器)執行垃圾回收的重點區域。

二.堆空間細分

  

 

 

  Java7及以前將堆空間邏輯上分成三部分:新生區+養老區+永久代

  Java8及以后將堆內存邏輯上分為:新生區+養老區+元空間

  新生代:

              1.新生代使用了復制算法
              2.新生代為gc的重點對象,經官方測試70%對象都生命周期都會在新生代中完結
              3.新生代又分為了eden、survivor1、survivor2,對象創建先放在eden中,經過一定時間還幸存就會放在幸存者區
              4.內存比例分默認為:8:1:1
              5.新生代收集器:Minor GC/Young GC

  

       eden(新生區)

​       當初始加載對象時會進入新生區

        survivor(幸存區)

            幸存區又分為from 和 to —誰為空誰為to ,始終都會有一個區域為空。

           幸存區不會主動進行垃圾回收,只會eden回收時才會附帶進行gc

           當在幸存區中的閾值達到了15后(默認15可修改)會自動進入老年代

​           當新生區(eden)出現了內存不足時,會進行YGC,那么會將沒有指針的對象回收,還有指針引向的對象放入survivor1或者survivor2區域中,eden清空,數據放入一個survivor中。—當第二次進行gc那么會將eden數據放入另一個空的survivor中,並且將當前survivor中有效數據,放入空的survivor中,一次類推。

 

  老年代

   1.較大的對象數據會放入老年代

          2.年代的數據都是相對於持久的不會頻繁的gc

          3.(MajorGC / Old GC) 在進行majorgc時會至少進行一次minorGc ,而且majorgc的效率是比minorGc 慢10倍的
          4.老年代收集器:MajorGC / Old GC 要區分與Full GC

    

 

 

                   在一個對象進入內存時 會進入eden,如果滿了(YGC進行回收沒有引用的,如果還有引用的)會放入s1或者s0這就涉及到to from哪個為空就是to,(下次eden再次滿了會將有數據的【舉例s1】中   的數據放入s0,並且進行迭代版本)以此類推,當某個對象迭代閾值的次數達到默認15此后,(當然也會有特殊的優化:如當survivor區域中相同年齡的內存總和大於survivor的一半內存,會將大於等於平均年齡的對象提前放入老年代)會放入老年代 關於YGC 全程(YoungGC) 也可以為(Minor GC) s1,0是不會有單獨的gc回收只會被動的依賴於eden的gc當eden進行gc時會自動回收s1,s0

 

 

 

    yangGC只會在eden區滿的時候進行,不會在survivor區滿的時候進行,eden區GC時也會把survivor區進行GC,當survivor中age=15時會將數據放入老年區。

三為什么分代

  

 

 

 四內存分配策略(或對象提升規則)

    如果對象在EDEN出生並且經過一次MinnorGC后依然存活,並且能被Survivor容納的話,將會被放在幸存者區,並將對象年齡設為1,每熬過一次MinnorGC,age增加一歲,當age增加到15時,會被放入老年代

五.TLAB

 

 

 

 

 

 

 

 

 

 

六逃逸分析

什么是逃逸?

​ 也就是如果在方法內創建對象,並且return進行傳出,或者賦值到外部的變量,那么就進行了逃逸。

​ -XX:+DoEscapeAnalysis (JDK1.8之后默認開啟)

​ -XX:+DoEscapeAnalysis(關閉)

逃逸分析包括以下

棧上分配

也就是將對象直接分配到棧上,跟隨棧的消亡而消亡,減少了gc(棧中沒有gc),提高了性能、速度。

同步省略

因為是每個棧獨有的,一個棧也就是一個線程所以不存在同步安全的問題。

分離對象或者標量替換

擴充:一個類代表一個:聚合量,標量是無法分析的最小數據,聚合量可以分析為標量,也就是分析屬性

也就是當加載一個pojo類時,不會創建對象而是,標量替換進行分析成一個個小的屬性,減少了內存,提高了性能。

但是基於hotSpot 虛擬機這項技術並不成熟,因為還需要進行判斷是否 屬於逃逸,如果沒有逃逸,可能會浪費了判斷的時間等一些問題。
但是最后標量替換還是引用到了hotSpot虛擬機中

所以問題—所有的對象都是存儲在堆空間中么?

回答:是的

總結

       1.爭對幸存者S0和S1區的總結:復制之后有交換,誰跟誰是to

  2.關於垃圾回收:頻繁在新生代中收集,很少在養老區收集,幾乎不在永久代/元空間中收集

  3.對象的執行流程

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM