方法区概述
方法区线程共享。
方法区大小决定系统可以保存多少个类。
关闭JVM就会释放该区内存。
方法区演进
JDK7之前,永久代。JDK8开始,元空间。元空间不在虚拟机设置的内存中,而是使用本地内存。
方法区大小设置
方法区大小不必是固定的,JVM可以根据应用的需要动态调整。
JDK8使用参数:-XX:MetaspaceSize和-XX:MaxMetaspaceSize。默认最小21M,最大值依赖平台大小。
如果元空间发生溢出,即超出本地内存,会抛出OOM异常。
-XX:MetaspaceSize过低,会频繁的触发full GC。
方法区内部结构
常量池
一个有效的字节码文件中除了包含类的版本信息、字段、方法以及接口等信息外,还包含常量池表(Constant Pool Table),包括各种字面量和对类型、域和方法的符号引用。
常量池的作用:不使用常量池可以使字节码文件更简短,只是一些符号,方便引用。
常量池可以看作一张表,虚拟机指令根据这张常量表找到需要执行的类名、方法、参数类型、字面量等信息。
运行时常量池
运行时常量池就是字节码常量池加载到jvm运行时的值。
StringTable
jdk7将StringTable放到了堆空间。因为永久代回收效率很低,在fullgc的时候才会触发。放在堆里可以及时回收。
静态变量存储位置
方法区垃圾回收
JVM规范对方法区的垃圾回收非常宽松,虚拟机可以不实现该区的垃圾回收。
方法区的垃圾回收主要包含2部分:常量池中废弃的常量和不再使用的类型。