Java 8 中的 MetaSpace 和示例
在每种编程语言中,内存都是至关重要的资源,而且在本质上也是稀缺资源。因此,必须彻底管理内存而没有任何泄漏。在本文中,我们将了解什么是元空间以及它与 permgen 有何不同。
在了解元空间之前,让我们先了解一下 JVM 内存结构。
JVM内存结构:
JVM 定义了在程序执行期间使用的各种运行时数据区域。有些区域是由 JVM 创建的,而有些是由程序中使用的线程创建的。但是,JVM 创建的内存区域只有在 JVM 退出时才会被销毁。线程的数据区在实例化时创建,在线程退出时销毁。 JVM内存结构分为多个内存区域,如堆区、堆栈区、方法区、PC寄存器等。下图说明了Java中不同的内存区域:
这里,堆区是JVM最重要的内存区域之一。这里存储了所有的Java对象。堆是在 JVM 启动时创建的。堆一般分为两部分。那是:
- Young Generation(Nursery):所有新对象都分配在这块内存中。每当此内存被填满时,就会执行垃圾收集。这称为Minor Garbage Collection 。
- 老年代:所有经过多次次要垃圾回收的长寿命对象都存储在该区域中。每当此内存被填满时,就会执行垃圾收集。这称为主要垃圾收集。
除了堆内存之外,JVM 还包含另一种类型的内存,称为永久代或“PermGen”。
PermGen Memory:这是Java堆中的一个特殊空间,它与存储所有静态内容的主内存分开。除此之外,此内存还存储 JVM 所需的应用程序元数据。元数据是用于描述数据的数据。在这里,垃圾收集也像内存的任何其他部分一样发生。在Java 7 之前,字符串池也是该内存的一部分。方法区是 PermGen 中空间的一部分,用于存储类结构以及方法和构造函数的代码。 PermGen 的最大缺点是它包含有限的大小,这会导致 OutOfMemoryError。 PermGen 内存的默认大小在 32 位 JVM 上为 64 MB,在 64 位版本上为 82 MB。因此,JVM 不得不通过频繁执行垃圾收集来更改此内存的大小,这是一项昂贵的操作。 Java还允许手动更改 PermGen 内存的大小。但是,PermGen 空间不能自动增加。因此,很难对其进行调整。而且,垃圾收集器的效率不足以清理内存。
由于上述问题, Java 8 中已经完全移除了 PermGen。在 PermGen 的位置,引入了一个名为 Meta Space 的新特性。 MetaSpace 默认自动增长。在这里,当类元数据使用量达到其最大元空间大小时,会自动触发垃圾收集。
下表描述了元空间和 PermGen 之间的区别:
PermGen MetaSpace It is removed from java 8. It is introduced in Java 8. PermGen always has a fixed maximum size. Metaspace by default auto increases its size depending on the underlying OS. Contiguous Java Heap Memory. Native Memory(provided by underlying OS). Inefficient garbage collection. Efficient garbage collection.