方法区 和 堆 的说明(学习笔记)

1、方法区(Method Area),又称永久代(Permanent Generation),又称非堆区(Non-Heap space)

方法区,又称永久代(Permanent Generation),常称为PermGen,位于非堆空间,又称非堆区(Non-Heap space)。

方法区是被所有线程共享。
所有字段和方法字节码,以及一些特殊方法如构造函数,接口代码也在此定义。
简单说,所有定义的方法的信息都保存在该区域,此区属于共享区间。

静态变量 + 常量 + 类信息(构造方法/接口定义) + 运行时常量池存 在方法区中 。

但是, 实例变量 存在 堆内存 中,和方法区无关。

以上,只是逻辑上的定义。在HotSpot中,方法区仅仅只是逻辑上的独立,实际上还是包含在Java堆中,也是就说,方式区在物理上属于Java堆区中的一部分,而永久区(Permanent Generation)就是方法区的实现。

2、堆 (heap)

一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的。类加载器读取了类文件后,需要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,以方便执行器执行。

堆 在逻辑上分为三部分 新生区 + 养老区 + 永久区(Perm)

  • 新生代(Young Generation,常称为YoungGen),位于堆空间;
  • 老年代(Old Generation,常称为OldGen、TenuringGen),位于堆空间;
  • 永久代(Permanent Generation,常称为PermGen),位于非堆空间。

2.1、新生区(New/Young Generation)

新生代(Young Generation),常称为YoungGen,位于堆空间;

新生区 又分为 Eden区 和 Survior(幸存区)。
Eden : 新创建的对象
Survior 0、1:经过垃圾回收,但是垃圾回收次数小于15次的对象

2.2、养老代(Old Generation)

老年代(Old Generation),常称为OldGen,位于堆空间;

Old : 垃圾回收次数超过15次,依然存活的对象

2.3、永久区(Permanent Generation)

永久代(Permanent Generation),常称为 PermGen,位于非堆空间。

永久区是一个常驻内存区域,用于存放JDK自身所携带的 Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭 JVM 才会释放此区域所占用的内存。

如果出现 java.lang.OutOfMemoryError: PermGen space ,说明是Java虚拟机对永久代Perm内存设置不够。一般出现这种情况,都是程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。或者大量动态反射生成的类不断被加载,最终导致Perm区被占满。

2.3.1、方法区的实现的演变:

  1. Jdk1.7之前:hotspot虚拟机对方法区的实现为永久代 ;
  2. Jdk1.8及之后:hotspot移除了永久代用 元空间(Metaspace)

2.3.2、运行时常量池存字符串常量池 的变化

  1. JDK1.7之前 :
    运行时常量池(包含 字符串常量池 )存放在 方法区,此时 hotspot 虚拟机对方法区的实现为永久代。

  2. JDK1.7 :
    字符串常量池 被从方法区拿到了堆中;
    运行时常量池 剩下的东西还在 方法区, 也就是hotspot中的永久代。

  3. JDK1.8 :
    hotspot移除了 永久代,用 元空间(Metaspace) 取而代之。这时候,
    字符串常量池还在堆,
    运行时常量池 还在方法区, 只不过方法区的实现从永久代变成元空间(Metaspace)

猜你喜欢

转载自blog.csdn.net/xiaojin21cen/article/details/87888409