JVM - 内存区域划分和异常

一、StackOverflowError

概述:如果线程请求的深度大于虚拟机所允许的深度,将抛出StackOverflowError异常
什么是栈的深度
- 栈在初始化过后是有一定的大小的。
- 栈的高度称为栈的深度,栈深度受栈帧大小影响。
局部变量表内容越多,栈帧越大,栈深度越小。

当我们定义的方法参数和局部变量过多,字节过大,考虑到可能会导致栈深度多小,可能使程序出现错误【递归的无限循环、两个方法互相调用、执行了大量方法,导致线程栈空间耗尽等都会发生栈溢出】。

如果程序本身没问题,这个时候就需要手动的增加栈的深度,避免出错。 例如 调整jvm 栈大小

C:\Users\rocky fang\Documents\mycode>java -Xss2m -cp "C:\Users\rocky fang\Documents\mycode" JavaStackTest
java.lang.StackOverflowError
stack height:23345

二、OutOfMemoryError

 什么情况下会发生?

JVM 中除了程序计数器外,其他区域都会发生OutOfMemoryError异常。

1、堆溢出

当发生堆的内存溢出时,会在异常信息后面跟随Java heap space的提示

2、虚拟机栈溢出

虚拟机扩展栈时无法申请到足够的内存空间或者线程申请栈空间失败。

要么是方法的深度太大了,导致了StackOverflowError异常。

要么是因为线程的数目太多了,堆栈的空间又比较大,导致了OutOfMemoryError异常,同时会打印unable to create native thread。由于Java的线程是映射到操作系统的内核线程上的,因此可能会导致操作系统假死。

3、方法区和运行时常量池溢出

运行时常量池是方法区的一部分,方法区用于存放Class的相关信息,如类名、访问修饰符、常量池、字段描述、方法描述等。JDK1.7之后,出现异常提示信息:java.lang.OutOfMemoryError: GC overhead limit exceeded

4、本机直接内存溢出

-XX:MaxDirectMemorySize:通过此参数来设定。如果不指定,默认与Java堆最大内存保持一致

HotSpot虚拟机的栈容量不可动态扩展,所以不会发生由于虚拟机栈无法扩展而导致的OOM异常

猜你喜欢

转载自blog.csdn.net/neusoft2016/article/details/123201478