方法区用于存放类信息、类加载器、运行时常量池等,方法区在jvm启动时创建,方法区是一套规范,不同的jvm厂商对于方法区实现有所不同。比如Oracle的hotspot虚拟机,在jdk1.8之前使用永久代实现方法区,永久代使用的是堆空间;在jdk1.8及之后使用元空间来实现方法区,元空间使用的是直接内存。方法区也存在内存溢出异常,如方法区加载过多类的二进制字节码会出现内存溢出错误。
图中的常量池,严谨来说应是运行时常量池。
使用jdk1.8版本 演示内存溢出错误package com.tech.metaspace;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
public class metaSpaceDemo_1 extends ClassLoader{ //自定义类加载器,加载类的二进制字节码
public static void main(String[] args) {
int j=0;
try {
metaSpaceDemo_1 metaSpaceDemo_1 = new metaSpaceDemo_1();
for (int i = 0; i < 10000; i++,j++) {
//ClassWriter 作用是生成类的二进制字节码
ClassWriter classWriter=new ClassWriter(0);
//版本号、public、类名、包名、父类、接口
classWriter.visit(Opcodes.V1_8,Opcodes.ACC_PUBLIC,"Class"+i,null,"java/lang/Object",null);
//返回byte数组
byte[] bytes = classWriter.toByteArray();
//执行了类的加载
metaSpaceDemo_1.defineClass("Class"+i,bytes,0,bytes.length);
}
} finally {
System.out.println(j);
}
}
}
在1.8版本方法区使用的直接内存,操作系统内存,也就是物理内存,通过jvm参数调小方法区空间,如改为10m
-XX:MaxmetaspaceSize=10m
运行后内存溢出错误
Exception in thread "main" java.lang.OutOfMemoryError: Compressed class space
在jdk1.8之前的版本,方法区空间大小设置如:
-XX:MaxPermSize=8m



