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,TenuringGen),位于堆空间
Old:垃圾回收次数超过15次,依然存活的对象
2.3永久区(Permanent Generation)
永久代(Permanent Generation),常称为PermGen,位于非堆空间。
永久区是一个常驻内存区域,用于存放JDK自身所携带的Class,Interface的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器收掉的,关闭JVM才会释放区域所占用的内存
2.3.1、方法区的实现的演变:
Jdk1.7之前:hotspot虚拟机对方法区的实现为永久代
Jdk1.8及之后,hotspot移除了永久代用元空间(Metaspace)
2.3.2、运行时常量池 和 字符串常量池 的变化
JDK1.7之前:
运行时常量池(包含字符串常量池)存放在方法区,此时hotspot虚拟机对方法区的实现为永久代
JDK1.7:
字符串常量池 被从方法区拿到了堆中
运行时常量池 剩下的东西还在方法区,也就是hotspot中的永久代
JDK1.8:
hotspot移除了永久代,用元空间(Metaspace)取而代之。这时候,字符串常量池还在堆中
运行时常量池还在方法区,只不过方法区的实现从永久代变成元空间(Metaspace)