第二章:Java虚拟机栈和本地方法栈溢出

Posted use-d

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第二章:Java虚拟机栈和本地方法栈溢出相关的知识,希望对你有一定的参考价值。

由于在Hotspot虚拟机中中不区分虚拟机栈和本地方法栈,因此通过-Xoss修改参数是无效的,可以通过修改-Xss设定。
  • 如果线程请求的栈深度大于虚拟机允许的最大深度,将抛出StackOverflowError异常。
  • 如果虚拟机在扩展栈时无法申请到足够的内存空间,将抛出OutOfMemoryError异常。
这两种异常有一些重叠的部分:当栈空间无法继续分配时,到底是内存太小,还是已经使用的栈空间过大,其本质只是对同一件事情的两种不同描述。
可以通过一下方法验证:
  • 在使用-Xss参数减少栈内存容量,结果抛出Stack OverflowError异常,异常出现时输出的堆栈深度相应缩小。
  • 定义了大量的本地变量,增大此方法栈中本地变量表的长度,结果抛出Stack OverflowError异常时输出的堆栈深度相应缩小。
可以通过递归调用的方式进行测试:
public void stackLeak() {
stackLeak();
}
通过不断建立线程的方式可以生产内存异常异常,但是产生的内存异常异常和栈空间是否足够大并不存在任何关联,在这种情况下,为每个线程的栈分配的内存越大,反而越容易产生内存溢出。
操作系统为虚拟机分配的内存时有限制的,如果虚拟机进程本身消耗的内存计算在内,剩余的内存就由虚拟机栈和本地方法栈瓜分了,每个线程分配到的栈容量越大,可以建立的线程数量自然就越少,建立线程时就越容易把剩下的内存耗尽。
如果是建立线程过多导致内存溢出,在不能减少线程数量或者更换64位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。
可以通过死循环创建线程的方式模拟“由于线程过多导致的内存溢出”:
while(true){
Thread t = new Thread。。。。
}

以上是关于第二章:Java虚拟机栈和本地方法栈溢出的主要内容,如果未能解决你的问题,请参考以下文章

Java虚拟机系列---内存溢出情况及解决方法

Java虚拟机栈和本地方法栈

46栈内存溢出内存区域(程序计数器Java 虚拟机栈本地方法栈Java 堆方法区直接内存内存溢出)与内存溢出(对象实例化分析)

JVM 运行时数据区:程序计数器Java 虚拟机栈和本地方法栈,方法区和堆

JVM学习

JVM运行时数据区之虚拟机栈,本地方法栈和程序计数器