堆,方法区,永久代,元空间 之间的关系

堆,方法区,永久代,元空间 之间的关系

  1. 方法区和永久代的关系

    方法区是 《Java虚拟机规范 》中的规范,在 HotSpot 虚拟机中,JDK 6.0 及以前由永久代实现,就如同 Java 中的接口和实现一样。

    永久代并不是很好的方法区实现,《Java虚拟机规范》中方法区不需要连续的内存并且可以选择固定大小或可扩展,而永久代有 -XX:MaxPermSize 上限,即使不设置也有默认大小,很容易造成内存溢出

  2. 堆和方法区的关系

    《Java虚拟机规范》把方法区描述为堆的逻辑部分,但它却有一个名字 Non-Heap 非堆,两者物理上并无联系。

    两者的共同点就是都可以选择固定大小或可扩展。

  3. 元空间:JDK 8 把永久代迁移到由本地内存实现的元空间当中

  4. 永久代数据迁移

    • 1.6 及以前永久代是方法区的实现,其中包括:已加载的类型信息,常量,静态变量,即时编译器编译过后的代码缓存等。
    • 1.7 将字符串常量池,静态变量移出到堆中。
    • 1.8 将老年代剩余内容(主要是类型信息)全部移到元空间中。
  5. 方法区的实现永久代真的永久吗?

    垃圾回收在这个区域出现的比较少,但是并不是没有,主要是常量池的回收和类型的卸载。主要是动态类的生成:CGLib字节码增强,JSP 等

  6. 永久代和元空间

    JDK 8 以后,永久代完全退出历史舞台,由元空间替代

  7. 常量池在 JDK 6,7,8 中存在位置证明

    import java.util.HashSet;
    import java.util.Set;
    
    public class RuntimeConstantPoolOOM {
        public static void main(String[] args) {
            Set<String> set = new HashSet<>();
            int i = 0;
            while (true){
                // String.intern();去字符串常量池中查找有没有这个字符串,有的话指向引用,没有将字符串拷贝进字符串常量池当中
                set.add(String.valueOf(i++).intern());
            }
        }
    }
    
    1. JDK 6:-XX:MaxPermSize 限制永久代大小,异常 OOM:PermGen space ,代表永久代空间不足,此时字符串常量池在永久代当中。
    2. JDK 7及以上:-XX:MaxPermSize 限制永久代大小,循环一直下去,不会爆异常。-Xmx 限制最大堆就可以看到 OOM:heap space堆内存不足,代表字符串常量池在中。在这里插入图片描述
已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页