定义
所有java 虚拟机线程共享的一块区域,存储了所有类相关信息,在虚拟机启动时被创建,JVM关闭就会释放方法区的空间。不同版本实现方式不同。例如永久代,元空间。
JDK1.6及之前:永久代。静态变量在永久代中
JDK1.7 :永久代。字符串常量池、静态变量移除,放入堆中。
JDK1.8及之后的实现方式:元空间。不在虚拟机设置的内存中,而是使用本地内存。类信息、字段、方法、常量保存在本地内存,但字符串常量池、静态变量仍在堆中。
方法区的内部结构
类的信息、属性、方法、异常表等。其中有他们的全类名,返回类型,权限修饰符等
被final修饰的属性在编译的时候就赋值了。
方法区内存溢出
类加载的个数过多
1. 1.8以前会导致永久代内存溢出(使用MaxPermSize设置永久代大小)
2. 1.8以后会导致元空间内存溢出(使用系统内存,可以使用MaxMetaSpace设置元空间大小)
溢出场景
加载大量的第三方的jar包:Tomcat部署的工程过多(30-50个):大量动态的生成反射类
实际场景中spring,mybatis:会产生大量的动态生成类
演示溢出
设置方法区内存大小
JDK 7 以前:
-XX:PermSize=100m
-XX:MaxPermSize=100m
JDK8及以后:
-XX:MetaspaceSize=100m
-XX:MaxMetaspaceSize=100m
如何解决OOM
方法区可以有垃圾回收也可以没有,方法区的垃圾收集主要回收两部分内容:常量池中废弃的常量和不再使用的类型。