前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java虚拟机OOM之虚拟机栈和本地方法栈溢出(4)

Java虚拟机OOM之虚拟机栈和本地方法栈溢出(4)

作者头像
Java后端技术
发布2018-08-09 10:53:28
7190
发布2018-08-09 10:53:28
举报
文章被收录于专栏:Java后端技术栈Java后端技术栈

一、在 Java 虚拟机规范中,对虚拟机栈这个区域规定了两种异常状况:

(1)如果线程请求的栈深度大于虚拟机所允许的深度,将抛出StackOverflowError 异常; (2)如果虚拟机栈可以动态扩展(当前大部分的 Java 虚拟机都可动态扩展,只不过 Java 虚拟机规范中也允许固定长度的虚拟机栈),当扩展时无法申请到足够的内存时会抛出 OutOfMemoryError 异常。 (3)与虚拟机栈一样,本地方法栈区域也会抛出 StackOverflowError 和OutOfMemoryError 异常。

二、前一篇文章中的第一张图也看出来了对于虚拟机栈和本地方法栈 如果在多线程的情况下是可能出现OOM的,下边就是一个单线程的案例。演示一下:

要设置VM Args: -Xss128k(上一篇已经说到:设置栈为128k),结果如下:

stack length:40550Exception in thread "main" java.lang.StackOverflowError at com.lc.oom.JavaVMStackSOF.stackLeak(JavaVMStackSOF.java:8) 后续很多异常省略。。。

结果表明:在单个线程下,无论是由于栈帧太大,还是虚拟机栈容量太小,当内存无法分配的时候,虚拟机抛出的都是 StackOverflowError 异常,而不是OOM。

三、如果测试时不限于单线程,通过不断地建立线程的方式倒是可以产生内存溢出异常。自己可以创建多个线程,进行测试,但是:由于在Windows 平台的虚拟机中, Java 的线程是映射到操作系统的内核线程上的,所以多线程代码执行时有较大的风险,可能会导致操作系统假死。所以。。。

不过结果肯定是,多线程的情况下,是会出现OOM的!

原理如下:

为什吗多线程的情况下就会产生OOM,这样产生的内存溢出异常与栈空间是否足够大并不存在任何联系,或者准确地说,在这种情况下,给每个线程的栈分配的内存越大,反而越容易产生内存溢出异常。

原因其实不难理解,操作系统分配给每个进程的内存是有限制的,譬如 32 位的 Windows 限制为 2GB。虚拟机提供了参数来控制 Java 堆和方法区的这两部分内存的最大值。剩余的内存为 2GB(操作系统限制)减去 Xmx(最大堆容量),再减去 MaxPermSize(最大方法区容量),程序计数器消耗内存很小,可以忽略掉。如果虚拟机进程本身耗费的内存不计算在内,剩下的内存就由虚拟机栈和本地方法栈“瓜分”了。每个线程分配到的栈容量越大,可以建立的线程数量自然就越少,建立线程时就越容易把剩下的内存耗尽。

更简单理解的就是:有一个操作系统为2G,我们分配给两个线程,每个800M,也就还剩400M,这样的话,有一个线程不够用的话,就会在400里边申请,所以如果剩下的越多,出现OOM的可能性越小,如果每个分配950M,这样就剩100M,这样的话出现OOM的可能性就更大。如果在增加线程,系统对每一个线程非配的内存是一定的,所以剩下的内存更少,这样的话,出现OOM的可能更大,但这都是相对而说。

遇到OOM这时候我们应该怎么做:

如果是建立过多线程导致的内存溢出,在不能减少线程数或者更换 64 位虚拟机的情况下,就只能通过减少最大堆和减少栈容量来换取更多的线程。如果没有这方面的经验,这种通过“减少内存”的手段来解决内存溢出的方式会比较难以想到。这种拆东墙补西墙的方法,还是自己意会吧。

<End>

版权声明:“Java后端技术”所推送文章,为本人原创、网上收集或其他作者投稿,对于网上收集部分除非确实无法确认,我们都会注明作者和来源。部分文章推送时未能与原作者取得联系。若涉及版权问题,烦请原作者联系我们,我们会在24小时内删除处理,谢谢!^_^ QQ:1573876303

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-10-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java后端技术 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档