久趣下载站

当前位置: 首页 » 游戏攻略 » 深入理解Java堆内存

深入理解Java堆内存

堆是JVM中最重要的一部分,规定了所有的对象和数组都应该存放在堆中。在执行字节码指令时,会将创建的对象存入堆中,对象的引用地址存入虚拟机栈的栈帧中。然而,当方法执行完毕后,刚刚创建的对象并不会立即被回收。相反,对象只有在JVM后台执行垃圾回收(GC)后才会被回收。

1. 指定堆大小

-Xms:指定堆的初始内存大小,ms(memory start)。等同于 -XX:InitialHeapSize;

-Xmx:指定堆的最大内存大小,mx(memory max)。等同于 -XX:MaxHeapSize;

通常会将 -Xms 和 -Xmx 设置为相同的值,这样JVM在GC后就不需要修改堆的内存大小,提高了效率。默认情况下,-Xms等于物理内存大小的1/64,-Xmx等于物理内存大小的1/4。

2. 新生代和老年代

垃圾回收算法通常将内存分为新生代和老年代两个区域。新生代存放新创建的对象,而老年代存放经过多次GC(默认为15次)后仍然存活的对象。

可以通过 -XX:NewRatio 参数配置老年代和新生代的比例,默认为 -XX:NewRatio=2,表示新生代占1,老年代占2。一般情况下不需要调整,只有在明确知道存活时间较长的对象偏多或偏少时才需要调整 -XX:NewRatio 的比值。

2.1 新生代

新生代又可分为伊甸园区(Eden)和幸存者区(S0、S1)。


Eden:

新对象都会先放到Eden区。


S0、S1区:

也称为幸存者0和幸存者1区,用于存放MinorGC(YGC)后存在的对象。

默认情况下,Eden、S0、S1的比例为8:1:1,即Eden区占新生代大小的8/10。可以通过 -XX:SurvivorRatio 来调整。

2.2 老年代

老年代存放经过多次GC后仍然存活的对象。老年代默认占内存区域的2/3。

2.3 动画演示

动画演示对象在内存各区域中的流转过程

  1. 对象会先被放到Eden区。
  2. 执行 Young GC 后会被放到S0或S1区,S0和S1不能同时非空,对象会在S0和S1之间反复跳跃。
  3. 在执行一定次数(默认为15次)的 Young GC 后假设对象还没有被回收掉,就会进入老年代区域。
  4. 如果新对象大小超过了Eden区剩余空间大小,则会直接进入S0或S1,如果S0或S1放不下则会直接进入老年代。
  5. 老年代继续执行 Old GC 对其中对象进行回收。

  6. 这里的 Young GC 和 Old GC 也可叫做 Minor GC 和 Major GC,它们并不是垃圾回收器的名字,只是代表年轻代和老年代的垃圾回收过程。

3. 分代收集理念

分代收集理念是垃圾回收算法的一种理念。几乎所有的垃圾回收算法都采用分代收集理念。

为什么垃圾回收算法要将内存区域分为新生代和老年代,新生代中又包含Eden区、幸存者区呢?

这是因为不同的对象存活时间不同,因此需要针对不同存活时长的对象采取不同的垃圾回收算法。

  • 新生代中的对象存活时间较短,适合采用“复制算法”(后面的章节会介绍)。
  • 老年代中的对象存活时间较长,不适合使用复制算法,可以使用“标记-清除算法”或“标记-整理算法”(后面的章节会介绍)。
猜你喜欢
本类排行