JVM運行時數據區 --- 堆

JVM運行時數據區 — 堆

堆的核心概述

首先 我們先了解堆空間位於運行時數據區的哪一個位置

在這裏插入圖片描述

  • 在這裏我們強調一個概念 一個進程對應一個JVM實例 一個JVM實例對應一個運行時數據區 運行時數據區獨立的只有一個方法區和一個堆 也就是說一個進程裏的多個線程要共享一個方法區和堆空間 而每個線程各自擁有一份程序計數器 本地方法棧 和 虛擬機棧

  • Java虛擬機規範中對Java堆的描述是 所有的對象實例和數組都應該在運行時分配在堆上

  • 數組和對象可能永遠不會存儲在棧上 因爲棧幀當中保存引用 這個引用指向對象或者數組在堆中的位置

  • 在方法結束後 堆中的對象不會被馬上的移除 僅僅在垃圾回收的時候纔會被移除

  • 堆的內存細分

    在這裏插入圖片描述
    在這裏插入圖片描述

設置堆內存大小與OOM

  • -Xms用來設置堆空間的初始內存大小 -Xmx用來設置堆空間的最大內存大小

  • 默認情況下 堆空間的大小

    初始內存大小 物理電腦內存大小/64

    最大內存大小 物理電腦內存/4

  • 查看設置的參數

    方式一 jps / jstat -gc 進程id

    方式二 -XX:printGCDetails

  • OOM

在這裏插入圖片描述

​ 此時發生了OOM異常 java.lang.OutOfMemoryError: Java Heap space

年輕代與老年代

在這裏插入圖片描述

  • 默認情況 新生代與老年代的比例是1:2
  • 默認情況 伊甸園與兩個倖存者的比例是8:1:1
  • 當我們加上 -XX: SurvivorRatio: 8 我們看到的結果就是8:1:1

圖解對象分配過程

在這裏插入圖片描述

1.首先 但我們最先開始new 對象的時候 我們將對象放到伊甸園區 當我們伊甸園區放滿的時候 就會觸發一次YGC 這時 我們先把垃圾先回收掉 也就是上圖的紅色部分是垃圾就會被回收了同時 我們將還存活的對象移動到倖存者0區 並將他們的年齡+1

在這裏插入圖片描述

2 通過上一次GC 我們伊甸園區已經空了 這是我們又在伊甸園區不斷的new對象 直到又一次把伊甸園區放滿了

​ 這個時候我們就觸發了第二次GC 這個時候我們進行2個操作

​ 第一 把Eden中存活的對象移動到s1區

​ 第二 對s0區的對象做一次判斷 看他們是不是垃圾現在 如果不是 就把s0區當中存活的對象移動到s1區

每次執行完gc之後 這兩個倖存者區當中誰空誰就是to區 這個to區表明了下一次YGC的時候Eden區中存活的對象 要往哪裏放

在這裏插入圖片描述

3 我們來看一種較爲特殊的情況 當我們執行一次YGC之後 我們還是按照剛剛的兩步(這時s0區是空的 作爲to區先是將Eden中的對象放到空的s0區當中 然後將s1區當中年齡是1的對象也放到s0區當中 然後把s1區當中年齡爲15的對象晉升到了老年區

特別的 這裏有一個注意點

什麼時候會觸發YGC

觸發YGC的條件是 當伊甸園區滿的時候會觸發YGC

survivor區滿了的時候不會觸發YGC 這個一定注意

當觸發YGC/Minor GC的時候 會將Eden中和survivor區中的對象一起回收

Minor GC — Major GC — Full GC

在這裏插入圖片描述

注意 Major GC只是老年代的垃圾收集 Full GC是整個Java 堆和方法區的收集

  • Minor GC的觸發機制
    • 當年輕代空間不足會觸發Minor GC 這裏的年輕代滿指的是Eden滿了 Survivor滿不會觸發GC
    • Java對象大多朝生夕死 所以Minor GC非常頻繁
    • Minor GC會引發STW 暫停用戶線程 等垃圾回收結束 用戶線程才恢復運行

內存分配策略

  • 優先分配到Eden

  • 大對象直接分配到老年代

  • 長期存活的對象分配到老年代

在這裏插入圖片描述

小結堆空間參數設置

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章