JVM(入门篇06)深入理解堆内存

一、堆内存的组成.

1.图解

JVM(入门篇06)深入理解堆内存_第1张图片

JDK1.8后永久区用元数据区(metaSpace)代替

JVM(入门篇06)深入理解堆内存_第2张图片

2. 堆内存溢出模拟.OOM(OutOfMemory)

/**
 * 堆内存溢出模拟
 */
public class Demo {
    public static void main(String[] args) {
        StringBuilder stringBuilder = new StringBuilder();
        while (true){
            stringBuilder.append("HelloHelloHelloHelloHelloHelloHello");
        }
    }
}

Run:

Exception in thread “main” java.lang.OutOfMemoryError: Java heap space

二、模拟垃圾回收的过程

1.实现

JVM(入门篇06)深入理解堆内存_第3张图片
2. JVM 调优参数

  • (1) -Xms: (初始内存 8m )
  • (2)-Xmx: (最大内存8m)
  • (3)-Xlog:gc* 打印所有垃圾回收器的信息
-Xms8m -Xmx8m -XX:-Xlog:gc*

JVM(入门篇06)深入理解堆内存_第4张图片
3.确定再Run

0.002s][warning][gc] -XX:+PrintGCDetails is deprecated. Will use -Xlog:gc* instead.
[0.011s][info   ][gc,heap] Heap region size: 1M
[0.012s][info   ][gc     ] Using G1
[0.012s][info   ][gc,heap,coops] Heap address: 0x00000000ff800000, size: 8 MB, Compressed Oops mode: 32-bit
[0.027s][info   ][gc           ] Periodic GC disabled
[0.080s][info   ][gc,start     ] GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation)
[0.080s][info   ][gc,task      ] GC(0) Using 2 workers of 10 for evacuation
[0.082s][info   ][gc,phases    ] GC(0)   Pre Evacuate Collection Set: 0.0ms
[0.082s][info   ][gc,phases    ] GC(0)   Evacuate Collection Set: 2.1ms
[0.082s][info   ][gc,phases    ] GC(0)   Post Evacuate Collection Set: 0.2ms
[0.082s][info   ][gc,phases    ] GC(0)   Other: 0.2ms
[0.082s][info   ][gc,heap      ] GC(0) Eden regions: 3->0(1)
[0.082s][info   ][gc,heap      ] GC(0) Survivor regions: 0->1(1)
[0.082s][info   ][gc,heap      ] GC(0) Old regions: 0->0
[0.082s][info   ][gc,heap      ] GC(0) Archive regions: 0->0
[0.082s][info   ][gc,heap      ] GC(0) Humongous regions: 3->2
[0.082s][info   ][gc,metaspace ] GC(0) Metaspace: 689K->689K(1056768K)
[0.082s][info   ][gc           ] GC(0) Pause Young (Concurrent Start) (G1 Humongous Allocation) 5M->2M(8M) 2.623ms
[0.082s][info   ][gc,cpu       ] GC(0) User=0.00s Sys=0.00s Real=0.00s
[0.082s][info   ][gc           ] GC(1) Concurrent Cycle
[0.082s][info   ][gc,marking   ] GC(1) Concurrent Clear Claimed Marks
[0.082s][info   ][gc,marking   ] GC(1) Concurrent Clear Claimed Marks 0.008ms
[0.082s][info   ][gc,marking   ] GC(1) Concurrent Scan Root Regions
[0.083s][info   ][gc,marking   ] GC(1) Concurrent Scan Root Regions 0.751ms
[0.083s][info   ][gc,marking   ] GC(1) Concurrent Mark (0.083s)
[0.083s][info   ][gc,marking   ] GC(1) Concurrent Mark From Roots
[0.083s][info   ][gc,task      ] GC(1) Using 3 workers of 3 for marking
[0.083s][info   ][gc,marking   ] GC(1) Concurrent Mark From Roots 0.251ms
[0.083s][info   ][gc,marking   ] GC(1) Concurrent Preclean
[0.084s][info   ][gc,marking   ] GC(1) Concurrent Preclean 0.149ms
[0.084s][info   ][gc,marking   ] GC(1) Concurrent Mark (0.083s, 0.084s) 0.431ms
[0.084s][info   ][gc,start     ] GC(1) Pause Remark
[0.084s][info   ][gc           ] GC(1) Pause Remark 5M->5M(8M) 0.444ms
[0.084s][info   ][gc,cpu       ] GC(1) User=0.00s Sys=0.00s Real=0.00s
[0.085s][info   ][gc,marking   ] GC(1) Concurrent Rebuild Remembered Sets
[0.085s][info   ][gc,marking   ] GC(1) Concurrent Rebuild Remembered Sets 0.099ms
[0.085s][info   ][gc,start     ] GC(1) Pause Cleanup
[0.085s][info   ][gc           ] GC(1) Pause Cleanup 5M->5M(8M) 0.075ms
[0.085s][info   ][gc,cpu       ] GC(1) User=0.00s Sys=0.00s Real=0.00s
[0.085s][info   ][gc,marking   ] GC(1) Concurrent Cleanup for Next Mark
[0.085s][info   ][gc,marking   ] GC(1) Concurrent Cleanup for Next Mark 0.115ms
[0.085s][info   ][gc           ] GC(1) Concurrent Cycle 2.811ms
[0.086s][info   ][gc,start     ] GC(2) Pause Young (Concurrent Start) (G1 Humongous Allocation)
[0.086s][info   ][gc,task      ] GC(2) Using 2 workers of 10 for evacuation
[0.087s][info   ][gc,phases    ] GC(2)   Pre Evacuate Collection Set: 0.0ms
[0.087s][info   ][gc,phases    ] GC(2)   Evacuate Collection Set: 1.4ms
[0.087s][info   ][gc,phases    ] GC(2)   Post Evacuate Collection Set: 0.3ms
[0.087s][info   ][gc,phases    ] GC(2)   Other: 0.1ms
[0.087s][info   ][gc,heap      ] GC(2) Eden regions: 1->0(1)
[0.087s][info   ][gc,heap      ] GC(2) Survivor regions: 1->0(1)
[0.087s][info   ][gc,heap      ] GC(2) Old regions: 0->1
[0.087s][info   ][gc,heap      ] GC(2) Archive regions: 0->0
[0.087s][info   ][gc,heap      ] GC(2) Humongous regions: 5->3
[0.087s][info   ][gc,metaspace ] GC(2) Metaspace: 771K->771K(1056768K)
[0.087s][info   ][gc           ] GC(2) Pause Young (Concurrent Start) (G1 Humongous Allocation) 5M->3M(8M) 1.851ms
[0.087s][info   ][gc,cpu       ] GC(2) User=0.02s Sys=0.00s Real=0.00s
[0.087s][info   ][gc           ] GC(3) Concurrent Cycle
[0.087s][info   ][gc,marking   ] GC(3) Concurrent Clear Claimed Marks
[0.087s][info   ][gc,marking   ] GC(3) Concurrent Clear Claimed Marks 0.005ms
[0.087s][info   ][gc,marking   ] GC(3) Concurrent Scan Root Regions
[0.088s][info   ][gc,marking   ] GC(3) Concurrent Scan Root Regions 0.537ms
[0.088s][info   ][gc,marking   ] GC(3) Concurrent Mark (0.088s)
[0.088s][info   ][gc,marking   ] GC(3) Concurrent Mark From Roots
[0.088s][info   ][gc,task      ] GC(3) Using 3 workers of 3 for marking
[0.088s][info   ][gc,start     ] GC(4) Pause Young (Normal) (G1 Humongous Allocation)
[0.088s][info   ][gc,task      ] GC(4) Using 2 workers of 10 for evacuation
[0.088s][info   ][gc,phases    ] GC(4)   Pre Evacuate Collection Set: 0.5ms
[0.088s][info   ][gc,phases    ] GC(4)   Evacuate Collection Set: 0.1ms
[0.088s][info   ][gc,phases    ] GC(4)   Post Evacuate Collection Set: 0.2ms
[0.088s][info   ][gc,phases    ] GC(4)   Other: 0.1ms
[0.088s][info   ][gc,heap      ] GC(4) Eden regions: 0->0(1)
[0.088s][info   ][gc,heap      ] GC(4) Survivor regions: 0->0(1)
[0.088s][info   ][gc,heap      ] GC(4) Old regions: 1->1
[0.088s][info   ][gc,heap      ] GC(4) Archive regions: 0->0
[0.088s][info   ][gc,heap      ] GC(4) Humongous regions: 3->3
[0.088s][info   ][gc,metaspace ] GC(4) Metaspace: 771K->771K(1056768K)
[0.088s][info   ][gc           ] GC(4) Pause Young (Normal) (G1 Humongous Allocation) 3M->3M(8M) 0.443ms
[0.088s][info   ][gc,cpu       ] GC(4) User=0.00s Sys=0.00s Real=0.00s
[0.088s][info   ][gc,task      ] GC(5) Using 1 workers of 10 for full compaction
[0.088s][info   ][gc,start     ] GC(5) Pause Full (G1 Humongous Allocation)
[0.089s][info   ][gc,phases,start] GC(5) Phase 1: Mark live objects
[0.090s][info   ][gc,phases      ] GC(5) Phase 1: Mark live objects 1.350ms
[0.090s][info   ][gc,phases,start] GC(5) Phase 2: Prepare for compaction
[0.090s][info   ][gc,phases      ] GC(5) Phase 2: Prepare for compaction 0.347ms
[0.090s][info   ][gc,phases,start] GC(5) Phase 3: Adjust pointers
[0.091s][info   ][gc,phases      ] GC(5) Phase 3: Adjust pointers 0.631ms
[0.091s][info   ][gc,phases,start] GC(5) Phase 4: Compact heap
[0.091s][info   ][gc,phases      ] GC(5) Phase 4: Compact heap 0.288ms
[0.091s][info   ][gc,heap        ] GC(5) Eden regions: 0->0(1)
[0.091s][info   ][gc,heap        ] GC(5) Survivor regions: 0->0(1)
[0.091s][info   ][gc,heap        ] GC(5) Old regions: 1->1
[0.091s][info   ][gc,heap        ] GC(5) Archive regions: 0->0
[0.091s][info   ][gc,heap        ] GC(5) Humongous regions: 3->3
[0.091s][info   ][gc,metaspace   ] GC(5) Metaspace: 771K->771K(1056768K)
[0.091s][info   ][gc             ] GC(5) Pause Full (G1 Humongous Allocation) 3M->3M(8M) 2.918ms
[0.091s][info   ][gc,cpu         ] GC(5) User=0.00s Sys=0.00s Real=0.00s
[0.091s][info   ][gc,task        ] GC(6) Using 1 workers of 10 for full compaction
[0.092s][info   ][gc,start       ] GC(6) Pause Full (G1 Humongous Allocation)
[0.092s][info   ][gc,phases,start] GC(6) Phase 1: Mark live objects
[0.093s][info   ][gc,phases      ] GC(6) Phase 1: Mark live objects 1.206ms
[0.093s][info   ][gc,phases,start] GC(6) Phase 2: Prepare for compaction
[0.093s][info   ][gc,phases      ] GC(6) Phase 2: Prepare for compaction 0.279ms
[0.093s][info   ][gc,phases,start] GC(6) Phase 3: Adjust pointers
[0.094s][info   ][gc,phases      ] GC(6) Phase 3: Adjust pointers 0.652ms
[0.094s][info   ][gc,phases,start] GC(6) Phase 4: Compact heap
[0.094s][info   ][gc,phases      ] GC(6) Phase 4: Compact heap 0.278ms
[0.094s][info   ][gc,heap        ] GC(6) Eden regions: 0->0(1)
[0.094s][info   ][gc,heap        ] GC(6) Survivor regions: 0->0(1)
[0.094s][info   ][gc,heap        ] GC(6) Old regions: 1->1
[0.094s][info   ][gc,heap        ] GC(6) Archive regions: 0->0
[0.094s][info   ][gc,heap        ] GC(6) Humongous regions: 3->3
[0.094s][info   ][gc,metaspace   ] GC(6) Metaspace: 771K->771K(1056768K)
[0.094s][info   ][gc             ] GC(6) Pause Full (G1 Humongous Allocation) 3M->3M(8M) 2.747ms
[0.094s][info   ][gc,cpu         ] GC(6) User=0.00s Sys=0.00s Real=0.00s
[0.094s][info   ][gc,marking     ] GC(3) Concurrent Mark From Roots 6.384ms
[0.094s][info   ][gc,marking     ] GC(3) Concurrent Mark Abort
[0.094s][info   ][gc             ] GC(3) Concurrent Cycle 6.986ms
[0.095s][info   ][gc,heap,exit   ] Heap
[0.095s][info   ][gc,heap,exit   ]  garbage-first heap   total 8192K, used 4001K [0x00000000ff800000, 0x0000000100000000)
[0.095s][info   ][gc,heap,exit   ]   region size 1024K, 1 young (1024K), 0 survivors (0K)
[0.095s][info   ][gc,heap,exit   ]  Metaspace       used 815K, capacity 4534K, committed 4864K, reserved 1056768K
[0.095s][info   ][gc,heap,exit   ]   class space    used 74K, capacity 403K, committed 512K, reserved 1048576K
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.base/java.util.Arrays.copyOf(Arrays.java:3746)
	at java.base/java.lang.AbstractStringBuilder.ensureCapacityInternal(AbstractStringBuilder.java:227)
	at java.base/java.lang.AbstractStringBuilder.append(AbstractStringBuilder.java:593)
	at java.base/java.lang.StringBuilder.append(StringBuilder.java:172)
	at Java学习.JVM虚拟机.堆.堆内存溢出模拟.Demo.main(Demo.java:10)

Process finished with exit code 1

2. (基本)内存分配与回收策略

上面的输出太乱我们来分析下

1.如果Eden区满了,出发一次轻度垃圾回收 minor GC ,过程如下.

  • (1)比如Eden的10个空间满了,将还需要使用的对象 1 复制到 幸存区 0(幸存区0和1是动态替换的一般都有一个空白的)
  • (2)。将消亡的 9 个对象清理掉
    在这里插入图片描述

2.到下一次Eden区满了,就再 Minor GC ,

  • 1.将Eden存活的(假设1个)对象复制到幸存区1中
  • 2.清理Eden区消亡的对象(假设9个)
  • 3.将 幸存0区 的对象(假设3个),存活的复制到幸存1区
  • 4.将 幸存0区 的对象(假设3个-1个),能晋升的晋升到 老年区**(能晋升的条件??)**
  • 5.销毁幸存者0区 还剩下的 1个对象.

注释:
此时幸存者0区空白,下一次一般幸存者1区空白,所以一般都有一个幸存者空白的)

在这里插入图片描述


3.15岁对象进入老年区.

(1)JVM给每个对象定义了一个年龄计数器
(2)如果对象在 Eden区出生,经过一次 轻度垃圾回收 Minor GC 后依旧存活,并且能被 幸存区 Survivor 容纳,对象的年龄就 为 1 ,没经过一次垃圾回收年龄+1,默认15岁,进入老年区

  • (可以JVM调优: -XX:MaxTenuringThreshold15)

3.(特殊01)大对象直接进入老年区.

1.什么是 – 大对 象?

(1)大量连续的内存空间的Java对象
(2)比如很长的字符串或者数组.

(3)JVM调参:-XX:PretenureSizeThreshold参数,大于这个参数的值就是大对象.

2.目的:避免在Enden 和 幸存区Survivor 之间发生多次大量内存的复制.

4.(特殊02)动态对象年龄判定

(1)对象并不是只有15岁才进入老年,
(2)当幸存区的某个年龄**(4岁)的所有对象空间大小的总合大于 幸存者空间的一半**,大于或者等于 (4岁)的对象直接进入老年区.

5.(特殊03)分担担保机制

(1)当发生Minor GC 的时候(需要重Eden转移的对象有20个),发现Survivor幸存者空间不足(只有10个),部分对象无法复制到Survivor幸存者空间,虚拟机可通过分担担保机制将这些对象提前转移到老年区

6 (特殊04)空间分配担保策略,

(1)GC 之前,虚拟机先检查老年区的最大可用连续空间是否大于新生区的所有的对象的总空间
(2)如果空间够大,GC绝对安全。(通过分担担保机制就能保证安全,)
(3)如果不够大,GC存在风险的可能,

  • 1.JVM 会查看 HandlePromotionFailure 设置是否可以冒险
  • 2.可以冒险,检查老年区最大可用连续空间是否大于晋升到老年对象的平均大小,
  • 3.如果可以冒险,并且 大于 老年对象平均大小---------Minor GC轻度清理.
  • 4.如果不能冒险,或者小于老年对象平均大小 -----------Full GC重度清理.

你可能感兴趣的:(JVM)