39.JVM运行时数据区之方法区概述
1.运行时数据区简单回顾
运行时数据区划分为下图所示的五个部分:
从线程共享与否的角度,可以划分为线程共享的堆和元空间。线程私有的是栈区、程序计数器、本地方法栈。
1.除了程序计数器,其它的区域都存在OOM
,其中栈区和本地方法栈还存在StackOverflow
。
2.堆区和元空间存在GC
。其它不存在GC
。
2.栈、堆、方法区的交互关系
从一行简单的代码看它们三者之间的关系:
Person person = new Person();
1.Person
类型信息放在了方法区(JDK8
及以后称为元空间);
2.person
变量存放在栈区,new
这个对象肯定实在一个方法中进行的,一个方法对应一个栈帧,栈帧中有局部变量表,person
变量就存放在局部变量表中。
3.new Person()
创建出来的实例变量就存放在堆区(不是绝对,但因为还可以防止栈上,但是大部分情况都是放在堆区)。
3.方法区的理解
1.虽然Java
虚拟机规范规定了方法区在逻辑上是属于堆的一部分,但是HotSpot JVM
实现的时候,是将方法区和堆区分开的。
所以,方法区看作是一块独立于Java
堆的内存空间。
2.方法区是线程共享的。
3.方法区在JVM
启动的时候创建,实际物理内存可以不连续。
4.方法区的大小和堆区一样,可以固定大小或者可扩展。
5.方法区的大小,决定了它能够保存的类的个数,如果系统定义了太多的类,就会导致方法区溢出。(也就是能够加载的类的个数,如果方法区很小,那么程序运行的时候,加载到内存中的类的个数就不能太多,否则会出错。)
6.关闭虚拟机,方法区的内存区域就会被释放。
4.HotSpot中方法区的演进过程
1.JDK7
及以前,习惯上把方法区称为永久代;JDK8
及以后,使用元空间取代了永久代。
方法区是虚拟机规定的一个概念,永久代和元空间是落地实现。
可以把方法区看做是接口,永久代和元空间看做是接口的实现。
2.在HotSpot
虚拟机中,方法区和永久代是等价的。但是在别的虚拟机中,就不一定了,例如IBM J9
虚拟机的实现,根本就不存在永久代的概念。
3.JDK7
中方法区的落地实现是永久代。
4.JDK8
及以后方法区的落地实现是元空间。
5.JDK8
及以后的元空间与永久代的最大的区别在于:元空间不在虚拟机设置的内存中,而是直接使用的本地内存。
6.方法区无法满足新的内存分配需求时,将抛出OOM
。