2011年5月28日星期六

JVM_027:奇怪的错误:OutOfMemoryError: unable to create new native thread

最近在做SOA方面的实验,在发布一个SOA应用时,碰到了一个奇怪的错误:
OutOfMemoryError: unable to create new native thread。
一开始以为SOA应用,仔细检查了一遍,发现没有错误,重新Deploy,错误依旧。
于是怀疑开发时,哪里不小心“碰坏”了某个文件,于是干脆重头做了一遍应用,重新Deploy,错误依旧。
这下子可怪了,程序编译没有错误,发布时却报出错误,于是仔细看了看这个错误:OutOfMemoryError: unable to create new native thread。

OutOfMemoryError?难道是内存不够用?
我安装的是32位的WebLogic Server,分配的内存是Xms512m Xmx1024m,难道还不够用?那就再加大。
经过测试,我发现32位的WebLogic Server的Xmx的上限是1612m(这是我用二分法一点一点测出来的,不能再高了,1613m就无法启动)。
先别着急Deploy,难道这个最大值才能到1612m,不让人感到奇怪吗?
按道理来说,32位的进程应该最多可以使用2的32次方的内存:即4G啊。怎么连一半都不到呢?
原来4G只是个理论值,在Windows平台上,每一个32位的进程最多可以使用2G内存,另外2G被操作系统保留。
再次Deploy, 以为这下总该成功了,结果,嘿嘿,还是错误依旧。
这就有些不讲道理了,我已经设置到了最大值1612m,内存怎么还是不够用啊。

“unable to create new native thread”,不应该啊,莫非线程使用的内存不是Xmx1612m中的内存?
还真让您给猜着了:原来Java每创建一个线程,除了在Heap中创建了一个Thread对象外,同时在操作系统中也创建了一个物理线程(参考JVM规范),操作系统会在剩余下的空间中(这里是2000-1612=388m)创建这个物理线程,而不是在1612m中里创建。
jdk1.4中默认的栈大小是256KB;jdk1.5中默认的栈大小为1M每线程,因此,在余下的388m中最多能创建388个线程,当然这是理论值,考虑到损耗,应该不到388个。

结论出来了:如果想创建更多的线程,就必须减少分配给JVM的最大内存。

我试着把WebLogic Server内存改为Xms512m Xmx512m,重新启动,发布,终于......成功了!

后记:为了彻底解决这个问题,我们不能眼巴巴地等着厂家出下一个版本,我试着重新安装了一个64位的JDK,
重新安装了WebLogic Server,SOA Suite,OSB。
重新发布SOA 应用,错误......终于消失了。

参考文献:
1. http://hi.baidu.com/hexiong/blog/item/16dc9e518fb10c2542a75b3c.html。

没有评论: