JVM学习--堆内存分析

JVM学习--堆内存分析

本章学习堆内存模型、对象分配和对象生命周期原理。部分内容参考Oracle官网以及咕泡学院教材。分析版本为jdk1.8。

@

对象创建

public static void main(String[] args) {
    Object o = new Object();
}

在java中,一个对象的创建会在java堆中分配一块内存空间。而在java堆中,并不是简单的直接将所有对象都放在一起,而是将java堆划分成了两块区域。一块是年轻代(Young Gen)、一块是老年代(Old Gen)。接下来分别介绍相应分代策略。

分代区域--Young Gen

年轻代(Young Gen),顾名思义,在这块区域中的对象属于新生对象,新生的定义为经过多轮gc之前的对象(在jvm中可以通过XX:MaxTenuringThreshold参数配置,默认15)。区分出年轻代的意义在于,在程序中,大多数的对象都是朝生夕死的,而在垃圾回收的时候,将这部分朝生夕死的对象与其他区分开,以提高垃圾回收的效率。但是又会产生内存空间不连续的问题(后面会提到产生的原因),因此实际在年轻代中,又将通过划分出EdenSurvivor来解决内存空间不连续的问题。

Eden

新生的对象都会被分配在Eden,大对象除外(对象占用的内存大小以及超过Eden所能容纳的大小)。

Survivor

Eden中的对象经过gc后存放在survivor区。survivor分为两个部分,同一时间,其中一个区域为空。

为空的原因是因为在年轻代中采用的复制算法(垃圾回收算法)会将survivor区中的从s0复制到s1,然后清除s0中的垃圾对象以达到整理对象内存空间,解决内存空间不连续的问题。

经过多轮回收后依然存活的对象,进入老年代(Old Gen)中。

Eden与survivor的区域比例可以通过-XX:SurvivorRatio参数配置,默认Eden:survivor比例为(8:2)

分代区域--Old Gen

老年代(Old Gen),顾名思义,在这块区域中的对象属于对象,老的定义为经过多轮gc后依然存活的对象(大对象除外)。老年代与年轻代的比例可以通过-XX:NewRatio参数配置,默认Young:Old比例为(1:4)。

对象生命周期图解

java对象生命周期(出生)

在这里插入图片描述

java对象生命周期(消亡)

在这里插入图片描述

常见问题

  • 如何理解Minor/Major/Full GC

    Minor GC:新生代GC

    Major GC:老年代GC

    Full GC:Minor + Major GC

  • 为什么需要Survivor区?只有Eden不行吗?

    如果没有Survivor,Eden区每进行一次Minor GC ,并且没有年龄限制的话, 存活的对象就会被送到老年代。
    这样一来,老年代很快被填满,触发Major GC(因为Major GC一般伴随着Minor GC,也可以看做触发了Full GC)。
    老年代的内存空间远大于新生代,进行一次Full GC消耗的时间比Minor GC长得多。
    执行时间长有什么坏处?频发的Full GC消耗的时间很长,会影响大型程序的执行和响应速度。
    可能你会说,那就对老年代的空间进行增加或者较少咯。
    假如增加老年代空间,更多存活对象才能填满老年代。虽然降低Full GC频率,但是随着老年代空间加大,一旦发生Full
    GC,执行所需要的时间更长。
    假如减少老年代空间,虽然Full GC所需时间减少,但是老年代很快被存活对象填满,Full GC频率增加。
    所以Survivor的存在意义,就是减少被送到老年代的对象,进而减少Full GC的发生,Survivor的预筛选保证,只有经历16
    次Minor GC还能在新生代中存活的对象,才会被送到老年代。

  • 为什么需要两个Survivor区?

    最大的好处就是解决了碎片化。也就是说为什么一个Survivor区不行?第一部分中,我们知道了必须设置Survivor区。假设
    现在只有一个Survivor区,我们来模拟一下流程:
    刚刚新建的对象在Eden中,一旦Eden满了,触发一次Minor GC,Eden中的存活对象就会被移动到Survivor区。这样继续循
    环下去,下一次Eden满了的时候,问题来了,此时进行Minor GC,Eden和Survivor各有一些存活对象,如果此时把Eden区的
    存活对象硬放到Survivor区,很明显这两部分对象所占有的内存是不连续的,也就导致了内存碎片化。
    永远有一个Survivor space是空的,另一个非空的Survivor space无碎片。

  • 新生代中Eden:S1:S2为什么是8:1:1?

    新生代中的可用内存:复制算法用来担保的内存为9:1
    可用内存中Eden:S1区为8:1
    即新生代中Eden:S1:S2 = 8:1:1

-- 摘要自咕泡学院教材

posted @ 2022-03-03 15:15  生如梦境  阅读(141)  评论(0编辑  收藏  举报