永久代(Permanent Generation)是早期JVM内存结构中的一个区域,用于存储类信息、方法区和常量池等数据。自Java 8起,永久代被元空间(Metaspace)代替。
元空间与永久代的主要区别如下:
- 存储内容:
- 永久代存储类信息、方法区和字符串常量池等。
- 元空间只存储类信息和方法区,字符串常量池移到了堆中。
- 空间大小限制:
- 永久代大小受MaxPermSize限制,默认为64M。
- 元空间大小仅受物理内存限制。
- GC回收:
- 永久代采用Serial或Parallel收集器进行回收。
- 元空间采用G1收集器进行回收。
- 管理方式:
- 永久代由JVM直接管理。
- 元空间由操作系统的本机内存管理系统直接管理。
来看一个简单例子:
我们可以编写两个Java程序,一个在Java 7下运行使用永久代,一个在Java 8下运行使用元空间,观察两者的区别。
Java 7程序:
public class PermanentGenerationDemo {
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
Foo.bar();
}
}
}
class Foo {
public static void bar() {
// 一个大字符串,存放在字符串常量池中,属于永久代
String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
}
}
运行这个程序,会观察到永久代的大小在不断增长,这是因为字符串常量池属于永久代,需要不断扩容。
Java 8程序:
public class MetaspaceDemo {
public static void main(String[] args) {
for (int i = 0; i < 100000; i++) {
Foo.bar();
}
}
}
class Foo {
public static void bar() {
// 一个大字符串,存放在堆中,不属于元空间
String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
}
}
运行这个程序,由于字符串常量池移到了堆,元空间的大小不会增长。所以,理解永久代和元空间的区别,可以帮助我们更好地管理程序的内存使用和调优。