Fork me on GitHub

OutOfMemoryError和StackOverflowError

内存区域划分

1.程序计数器:当前线程的正在执行的字节码指示器

2.虚拟机栈和本地方法栈:虚拟机栈存储局部变量表(包括方法入参和布局变量)、操作数栈、方法返回地址(调用者的栈帧,包括return返回和异常返回)等

3.堆:为几乎所有对象实例分配内存的区域

4.方法区:用于存储已被虚拟机加载的类信息、常量(static final)、静态变量(static)、即时编译器编译后的代码,是JVM规范中的一个逻辑概念,具体存放在哪里,由虚拟机实现。非堆

5.直接内存:使用操作系统的本地函数库分配的非堆内存,再通过Java的DirectByteBuffer对象引用这块内存

 

线程共享的区域:

堆、方法区、直接内存

线程隔离的区域:

程序计数器和栈

1.StackOverflowError出现的场景

线程的栈帧大小超出了jvm的设置的栈容量(-Xss可以设置虚拟机栈的容量,在HotSpot虚拟机中,不区分虚拟机栈和本地方法栈,所以在HotSpot虚拟机中-Xss设置的是栈大小),最常见的情况就是程序出现了错误的递归,导致在一个线程中栈帧的深度过大

JVM栈最大容量参数:-Xss2M

2.OutOfMemoryError出现的场景

1.堆:虚拟机中的对象,占用的内存容量大于JVM最大堆容量

JVM堆参数配置:

  1. 最小堆容量:-Xms2G。最大堆容量-Xmx4G
  2. 堆内存溢出dump文件:-XX:HeapDumpOnOutOfMemoryError

2.方法区内存溢出

在java1.6中的HotSpot虚拟机中,方法区用永久代实现。当永久代占用的内存大于JVM参数的永久代最大值时出现内存溢出

Java1.6-1.7的JVM永久代参数配置:

  最小永久代:-XX:PermSize=500m 最大永久代:-XX:MaxPermSize=1000m

Java1.8中利用元空间实现方法区,永久代的概念被移除了(-XX:MaxPermSize失去了意义),使用参数:

  最大元空间设置:-XX:MaxMetaspaceSize

3.直接内存溢出

直接内存容量大小默认与Java堆得最大值(-Xmx)相同,可以通过参数:-XX:MaxDirectMemorySize=1G指定

4.虚拟机栈和本地方法栈

创建的线程过多,亦或是JVM线程栈参数过大,导致操作系统无法继续创建新的线程,会出现OutOfMemoryError

 

3.Java进程占用内存总和

  堆+线程个数*栈帧容量+方法区+直接内存+操作系统占用内存

  参数配置:-Xmx + threadCount*-Xss+(-XX:MaxPermSize 或者 -XX:MaxMetaspaceSize)+-XXMaxDirectMemorySize

posted @ 2020-03-28 19:13  gitmoji  阅读(266)  评论(0编辑  收藏  举报