jdk7及以前:
通过-XX:PermSize 来设置永久代初始分配空间,默认值是20.75m
-XX:MaxPermSize来设定永久代最大可分配空间,32位是64m,64位是82m
jdk8及之后:
通过-XX:MetaspaceSize 来设置永久代初始分配空间,默认值是21m
-XX:MaxMetaspaceSize来设定永久代最大可分配空间,值为-1
由于没有上限,因此当本机内存耗尽时,会抛出oom的错误,对于起始值21m来说,如果所使用的内存超过这个值,则会触发full gc卸载没用的类,之后将会重置这个初始值,新的初始值的高低在于gc后释放了多少的空间,释放得少则提升这个初始值,释放得多则降低这个初始值。因此在实际的开发场景中,为了减少full gc的频率,会将这个初始值设置大一些。
代码示例:
通过for循环不停创建类,直到溢出为止。
设置jvm参数:-XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m
package com.lydon.test;
import jdk.internal.org.objectweb.asm.ClassWriter;
import jdk.internal.org.objectweb.asm.Opcodes;
public class OOMTest extends ClassLoader{
public static void main(String[] args) {
int j=0;
OOMTest test =new OOMTest();
try{
for (int i = 0; i <100000 ; i++) {
ClassWriter classWriter=new ClassWriter(0);
//指明版本号,修饰符,类型,包名,父类,接口
classWriter.visit(Opcodes.V1_8,Opcodes.ACC_PUBLIC,"Class"+i,"com.lydon.test","java/lang/Object",null);
byte[] code=classWriter.toByteArray();
test.defineClass("Class"+i,code,0,code.length);
j++;
}
}catch (Exception e){
e.printStackTrace();
}finally {
System.out.println(j);
}
}
}
输出结果:
D:\Java\jdk1.8.0_121\bin\java.exe -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=10m "-javaagent:D:\IntelliJ IDEA 2021.1\lib\idea_rt.jar=63745:D:\IntelliJ IDEA 2021.1\bin" -Dfile.encoding=UTF-8 -classpath D:\Java\jdk1.8.0_121\jre\lib\charsets.jar;D:\Java\jdk1.8.0_121\jre\lib\deploy.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\access-bridge-64.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\cldrdata.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\dnsns.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\jaccess.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\jfxrt.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\localedata.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\nashorn.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\sunec.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\sunjce_provider.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\sunmscapi.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\sunpkcs11.jar;D:\Java\jdk1.8.0_121\jre\lib\ext\zipfs.jar;D:\Java\jdk1.8.0_121\jre\lib\javaws.jar;D:\Java\jdk1.8.0_121\jre\lib\jce.jar;D:\Java\jdk1.8.0_121\jre\lib\jfr.jar;D:\Java\jdk1.8.0_121\jre\lib\jfxswt.jar;D:\Java\jdk1.8.0_121\jre\lib\jsse.jar;D:\Java\jdk1.8.0_121\jre\lib\management-agent.jar;D:\Java\jdk1.8.0_121\jre\lib\plugin.jar;D:\Java\jdk1.8.0_121\jre\lib\resources.jar;D:\Java\jdk1.8.0_121\jre\lib\rt.jar;D:\workspace\jvm-demo\chapters09\target\classes com.lydon.test.OOMTest
8271
Exception in thread "main" java.lang.OutOfMemoryError: Metaspace
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at com.lydon.test.OOMTest.main(OOMTest.java:18)
Process finished with exit code 1