处理多代对象
Java 垃圾收集器实现了分代垃圾收集策略,可以按年龄对对象进行分类。
JVM 中的这种需要(标记和压缩所有对象)可以称为低效。由于分配了大量对象,因此它们的列表会增长,从而导致垃圾收集时间增加。对应用程序的实证分析表明,Java 中的大多数对象都是短暂的。
JVM中的堆内存区分为三部分:

年轻一代
新创建的对象从年轻一代开始。年轻一代进一步细分为两类。
- Eden Space - 所有新对象都从这里开始,它们被分配初始内存。
幸存者空间(FromSpace 和 ToSpace)——对象在一个垃圾收集周期后从 Eden 移动到这里。
从年轻代收集对象的过程称为次要垃圾收集事件。
当 Eden 的空间充满对象时,将执行小型垃圾收集。所有死物体都被移除,所有活物体都被移动到剩下的两个空间之一。小型 GC 还会检查幸存者空间中的对象并将它们移动到另一个(下一个)幸存者空间。
让我们以下面的序列为例。
- 伊甸园中有两种类型的物体(活的和死的)。
- 发生小型 GC - 所有死对象都从伊甸园中移除。所有有生命的物体都被移动到 space-1 (FromSpace)。Eden 和 space-2 现在是空的。
- 新对象被创建并添加到伊甸园。Eden 和 space-1 中的一些物体变得死了。
- 发生小型 GC - 所有死对象都从 Eden 和 space-1 中删除。所有有生命的物体都被移动到空间 2 (ToSpace)。Eden 和 space-1 是空的。
因此,在任何时候,其中一个幸存者空间总是空的。当幸存者达到通过幸存者空间移动的某个阈值时,他们会前进到老一代。
您可以使用-Xmn标志来设置新生代的大小。
老一代
存在很长一段时间(例如,程序生命周期的大部分时间)的对象最终会变成更老的对象——百岁老人。它也被称为常规生成,包含长期留在 Survivor Spaces 中的对象。
一个对象的生命周期阈值决定了它在被移动到老年代之前必须经历多少个垃圾收集周期。对象从老年代发送到垃圾中的过程称为主垃圾回收事件。
您可以使用-Xms和-Xmx标志来设置初始和最大堆内存大小。
因为 Java 使用分代垃圾收集,对象经历的垃圾收集事件越多,它在堆上移动的越远。他从年轻一代开始,如果他活得足够长,最终会在普通一代结束。
要了解对象在空间和世代之间的提升,请考虑以下示例:
当一个对象被创建时,它首先被放置在年轻代的伊甸园空间中。
一旦发生小型垃圾回收,Eden 中的活动对象就会被移动到 FromSpace。当下一次次要垃圾回收发生时,Eden 和空间中的活动对象都被移动到 ToSpace。
这个循环持续一定次数。如果该对象在此之后仍在“服务中”,则下一个垃圾收集周期会将其移至老年代空间。
永久代和元空间
类和方法等元数据存储在持久代中。JVM 根据应用程序使用的类在运行时填充它。不再使用的类可以从永久代变成垃圾。
您可以使用-XX:PermGen和-XX:MaxPermGen标志来设置永久代的初始大小和最大大小。
元空间
从 Java 8 开始,PermGen 空间被 MetaSpace 内存空间取代。该实现与 PermGen 不同——此堆空间现在会自动更改。
这避免了应用程序由于 PermGen 的堆空间大小有限而出现的内存不足问题。元空间内存可以被垃圾回收,当元空间达到最大大小时,不再使用的类将被自动清理。
GO TO FULL VERSION