一、oom设计
private static void test(){ int i=0; List<Object> list = new ArrayList<>(); while(true){ System.out.println(i++); list.add(new Object()); } }
写了如上方法,在main()方法中调用后,发现虽然堆区满了,但是也并没有出现oom,查阅发现java8因为Metaspace,所以并不是堆区满了就出现oom,所以配置如下参数:-Xmx56m -XX:MaxMetaspaceSize=128m 设置最大堆区为56m,设置最大Metaspace为128m,运行程序后,抛出了oom。
二、原因总结
1.JDK8 HotSpot JVM 移除了永久代(方法区),使用本地内存来存储类元数据信息并称之为:元空间(Metaspace),如下图所示:
2.java8中metaspace总结:
a.移除了PermGen 空间
b.大部分类元数据(Metaspace )都在本地内存中分配。
默认情况下,类元数据只受可用的本地内存限制
新参数(MaxMetaspaceSize)用于限制本地内存分配给类元数据的大小。如果没有指定这个参数,元空间会在运行时根据需要动态调整(意思是如果不设置MaxMetaspaceSize,则一直可能会占用完所有的物理内存,而物理内存占用过高,可能会被操作系统kill掉)。
三、方法区和永久代
1.方法区是所有线程共享的,主要用于存储类的信息、常量池、方法数据、方法代码等。通常又叫“非堆”。
2.PermGen(永久代)
对于 “java.lang.OutOfMemoryError: PermGen space “这个异常。这里的 “PermGen space”其实指的就是方法区。
3.区别和联系
方法区是 JVM 的规范,而“PermGen space”后者则是 JVM 规范的一种实现,而且只有 HotSpot 才有 “PermGen space”,而对于其他类型的虚拟机则没有。