栈、堆、方法区交互关系
什么是方法区
尽管所有的方法区在逻辑上属于堆的一部分,但是一些简单的实现可能不会进行垃圾回收和压缩
各个线程共享区域
方法区在JVM启动时创建,并且它的实际的物理内存空间和java堆区一样都可以是不连续的
方法区的大小和堆空间一样,可以选择固定大小或者可扩性
方法区的大小决定了系统可以保存多少类,如果系统定义太多类导致方法区溢出 会抛出OOM
方法区大小的设置与OOM
1.7
-XX:PermSize 永久代初始分配空间
-XX:MaxPermSize 永久代最大可分配空间
1.8
-XX:MetaspaceSize 元空间初始分配大小 默认21M
-XX:MaxMetaspaceSize 元空间最大可分配空间
方法区的内部结构
一类型信息
对每个加载的类型,class、interface、enum、annotationJVM必须存储一下信息
1.这个类型的完整有效名称
2.这个类型的直接父类的完整有效名称
3.这个类型的修饰符
4.这个类型的直接接口的有序列表
域【Field】信息
1.域名称、声明顺序
2.域类型
3.域修饰符
方法method信息
1.方法名称
2.返回类型
3.方法参数的数量和类型 按顺序
4.方法的修饰符
5.方法的字节码、操作数栈、局部变量表以及大小 abstract和native方法除外
4.异常表
二常量 final 修饰的变量值在编译期间值就已经确定
三静态变量
四即时编译器编译后的代码缓存
五运行时常量池
字节码文件中的常量池constant Pool会在运行时加载到方法区成为运行时常量池
各种字面量和对类型、域方法的符号引用
数量值、字符串值、类引用、方法引用
具有动态性 String.intern
运行时常量池在1.7放在方法区中
1.8放在堆中