什么是永久代?在Java 8中永久代被什么代替了?代码举例讲解

永久代(Permanent Generation)是早期JVM内存结构中的一个区域,用于存储类信息、方法区和常量池等数据。自Java 8起,永久代被元空间(Metaspace)代替。

元空间与永久代的主要区别如下:

  1. 存储内容:
    • 永久代存储类信息、方法区和字符串常量池等。
    • 元空间只存储类信息和方法区,字符串常量池移到了堆中。
  2. 空间大小限制:
    • 永久代大小受MaxPermSize限制,默认为64M。
    • 元空间大小仅受物理内存限制。
  3. GC回收:
    • 永久代采用Serial或Parallel收集器进行回收。
    • 元空间采用G1收集器进行回收。
  4. 管理方式:
    • 永久代由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"; 
    } 
}

运行这个程序,由于字符串常量池移到了堆,元空间的大小不会增长。所以,理解永久代和元空间的区别,可以帮助我们更好地管理程序的内存使用和调优。