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

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