JVM 内存区域内存溢出

内存溢出以及堆栈溢出

简单认识一下2种内存异常OutOfMemoryError,StackOverflowError

来自JDK Doc的解释:

public class OutOfMemoryError extends VirtualMachineError

Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector. OutOfMemoryError objects may be constructed by the virtual machine as if suppression were disabled and/or the stack trace was not writable.

当JVM无法给对象分配足够的内存,并且GC收集器中也没有满足分配的内存空间时,抛出OOM异常。

public class StackOverflowError extends VirtualMachineError

Thrown when a stack overflow occurs because an application recurses too deeply.

当应用递归调用太深导致堆栈溢出时抛出SOF异常。

总结

1 线程请求的栈深度大于JVM允许的最大深度,抛出SOF异常

2 如果JVM的栈内存允许动态扩展,当栈扩展时无法申请到足够的内存,就抛出OOM异常。

环境

JDK 1.8 Win10x64

JAVA堆溢出

1.因为对象都是分配在JAVA堆上,所以以下代码操作触发堆溢出 ,配置

 -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 1 /**
 2  * VM Args: -Xms20m -Xmx20m -XX:+HeapDumpOnOutOfMemoryError
 3  * @author cxz
 4  * @Title:
 5  * @Package
 6  * @Description:
 7  * @date 2020/6/2811:03
 8  */
 9 public class HeapOOM {
10     static class OOMObject{
11     }
12     public static void main(String[] args) {
13         List<OOMObject> list = new ArrayList<OOMObject>();
14         while (true){
15             list.add(new OOMObject());
16         }
17     }
18 }

-Xss128k 设置减少栈内存容量,

 

不同版本的JVM和不同的OS,栈容量的最小值可能不同,JDK8 WIN_64,提示栈容量不能小于108K

3 定义N多局部变量,占满局部变量表空间

无论是栈帧太大还是JVM栈容量太小,当新的栈帧内存无法分配时,HotSpot都会抛出SOF异常

方法区,运行时常量池

JDK7之后,原本放在永久代的字符串常量池被移至JAVA堆之中,所以对字符串常量池的测试,就要对参数-Xmx修改

设置-Xmx6m

 

JDK8以后,元空间出现替代了永久代, HotSpot 提供了一些参数作为元空间的防御措施

-XX:MaxMetaspaceSize: 设置元空间最大值,默认-1,不限制【只受本地内存大小限制】

-XX:MetaspaceSize: 指定元空间的初始空间大小,以字节为单位,达到该值就会触发垃圾收集进行类型卸载,同时收集器会对该值进行调整: 如果释放了大量的空间,就适当降低该值;如果释放了很少的空间那么在不超过-XX:MaxMetaspaceSize的情况下,适当提高该值

-XX:MinMetaspaceFreeRatio 作用是在垃圾收集之后控制最小的元空间剩余容量的百分比,可减少因为元空间不足导致的垃圾收集的频率。

类似的还有-XX:MaxMetaspaceFreeRatio,用于控制最大的元空间剩余容量的百分比

 

参考:JDK8 Docs,《深入理解Java虚拟机:JVM高级特性与最佳实践》

原文地址:https://www.cnblogs.com/dreamtaker/p/13209974.html