什么是 Java 堆碎片?

Java 堆碎片是一种很有意思的问题,其会触发长时间的 Full GC 停顿周期。在本文中,我们将尝试对堆碎片进行解释。

假设开发人员写下了新的代码“new BMW()”。这行代码会在堆内存空间中创建一个新的 BMW 对象。示例:

图:JVM 堆内存中创建的新对象

我们假设程序创建了 3 个新的对象:“Toyota”、“Honda”、“Tesla”。现在 JVM 堆内存将变成这样:

图:JVM 堆内存中创建更多对象

假设一段时间后依然没有其他对象引用 Toyota 和 Tesla 对象,那么垃圾回收器将从内存中移除 Toyota 和 Tesla 对象。因此,在垃圾回收周期之后,堆内存会变成这样:

图:垃圾回收功能从 JVM 堆内存中移除未使用的对象

假设现在程序创建了一个新的“Truck”对象,该对象的大小更大。内存中虽然有足够的空间来容纳 Truck 对象,但我们能够看到,其中其实没有足够的连续空间,因为堆内存出现了碎片化。

图:JVM 堆内存出现碎片化,没有足够的连续空间来容纳“Truck”对象

出现这样的堆碎片时,Full GC 将被触发。Full GC 会开始压缩内存,即将 BMW 和 Honda 对象靠在一起,这样就有了足够的连续内存空间。通常而言,执行压缩工作的 Full GC 会使得 JVM 停顿更长时间。

注意:如需研究堆碎片情况与由于 Full GC 而导致的停顿时间,以及减少此类情形的步骤,您可以考虑使用免费的垃圾回收日志分析工具(如:GCeasy、Garbage Cat, HP Jmeter)

图:压缩后的 JVM 堆内存

压缩后将有足够的连续内存来存储 Truck 对象。因此 Truck 对象就可被存储在内存中了。

图:压缩后的 JVM 堆内存可容纳“Truck”对象

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Blog at WordPress.com.

Up ↑

%d bloggers like this: