[JVM]-OutOfMemoryError: unable to create new native thread

近来在系统的运行过程中碰到了一位老朋友,它正是大家所熟悉的OutOfMemory*,不过跟以前那位不太一样,它托着一个Error的尾巴,另外则是系统在抛出该例外时,并没有退出JVM实例。

那么这位改头换面的朋友究竟是何许人也,Google了一下居然也有一大片的介绍,甚至有些Blog已经探索到JVM寻址技术。这里赞一下,很好很强大,但如同我老大所说,精确到这层面,那么我们所能做的优化工作还剩多少?

Okay,看一下JDK的specification中对OutOfMemoryError 的描述:
Thrown when the Java Virtual Machine cannot allocate an object because it is out of memory, and no more memory could be made available by the garbage collector.
Umm, 这意思是在说由于没有更多的可用内存给GC或内存已经溢出,导致JVM无法分配新的对象,所以抛出OutOfMemoryError。我觉得这似乎在说Heap的内存溢出, 然而OutOfMemoryError完全是Stack中无法启动线程而抛出的异常。(大伙觉得java对outofmemoryerror的描述有没有问题?
看了这段简单的描述,我立马想到了JVM 的Xmx参数,难道由于Heap size 太小, 导致无法新生对象?

事实上,我的Heap Size 设置为2047M, 系统的日志记录着在OutOfMemory时, 已使用内存才300+M, 问题越来越离奇,难道是内存泄露么。为此,我通过Linux的pmap查到系统进程中,每个对象地址的使用内存大小, 以及通过jmap查看JVM的Heap 中对象的内存占用情况,都表明内存占用很正常。最后只能无功而返.

继续Google, 看到Sun的一个论坛里也有人提到:
[url]http://forums.sun.com/thread.jspa?threadID=605782&messageID=3360044[/url]
贴子里一个叫unsavory的人,他的解决方案是Threadpool, 意思是我们在生成销毁线程时,部分内存未被回收。最终导致了溢出,当然sun还有其他贴子说的更加离谱,说是在我们的项目中使用了RMI对象导致内存溢出。(摊手, 浪费了我不少时间.

[color=red]事实上, 回到主题, 该异常由栈中抛出, 表明栈中无可用内存来服务线程。而JVM的内存大致可分为(这里不够严谨)内存数据区(包括Stack)+对象堆区,由于JVM实例进程寻址是一定的。所以两者此消彼涨的关系,对于32位的机子, JVM整个实例可用内存不到3G,加上我的Heap Size 设置了2G,留给数据区只有1G不到, 当时系统跑了大概500+的线程, 按照JDK1.5以来, 每个线程栈的大小为1M, 这样算出溢出就差不多了. 解决方案是减小Heap Size 的大小给数据区留下内存, 或是增加CPU位数。[/color] :D
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值