参见英文答案 >
Java: Unable to create new native thread 6
我们有一个被广泛部署的应用程序(数百个工作站运行它).在一个站点(只有一个站点 – 我们的产品被广泛部署到许多环境),我们随机得到以下错误:
java.lang.OutOfMemoryError:无法创建新的本机线程
在java.lang.Thread.start0(本机方法)
在java.lang.Thread.start(未知来源)
操作系统是Windows 7 64位
我们正在运行一个32位JVM(1.7.0_45)
使用Windows任务管理器,我可以看到该进程有39个本机线程(不是很多),所以我们的应用程序没有线程泄漏…没有其他进程消耗大量线程(Explorer有35, jvisualvm有24,iexplore有20,…我没有确切的数量,但我们可能会看到可能300线程的用户总数).
我试图附加JVisualVM,但它无法连接到进程(可能是b / c的线程耗尽).但是从我可以从JVisualVM获得的指标中,Java线程的数量约为22个活动和11个守护进程.
堆的行为很好 – 堆是500MB,实际使用的是250MB.
该过程使用-Xmx512m启动
我们的过程正在显示597,744K的内存使用情况(在任务管理器中).
该工作站有8GB内存,其中只有3.8-4.0GB(我知道,一个32位进程不会访问所有这些,但仍然有很多)
使用的VMMap,堆栈是49,920KB大小与2,284K承诺.
该过程显示5358KB免费,免费列表中最大的可分配块大小为1,024K.
我使用资源监视器,它的提交(KB)为630428,工作集(KB)为676,996,可共享(KB)为79,252,私有(KB)为597,744
我在这里发生了什么事情完全丧失了.我已经阅读了大量的文章,这听起来像在一些Linux系统上,每个用户的线程限制可能会导致问题(但是这不是Linux,而其他文章中描述的问题通常会涉及到需要数千线程 – 绝对不是我们的情况)
如果我们的堆很大,我可以看到进入空间可用于线程,但是500MB似乎是一个非常合理和小的堆(特别是具有8GB RAM的工作站).
所以我已经耗尽了我所知道的一切 – 有没有人有什么可以在这里发生的事情呢?
编辑1:
他们建议堆栈大小可能是问题.
本文:where to find default XSS value for Sun/Oracle JVM? – 提供了一个指向Oracle文档的链接,说明默认堆栈大小为512KB.所以如果我的应用程序有大约40个线程,我们正在查看20 MB的堆栈. 500MB堆.这似乎完全符合32位Java进程的正常范围.
所以这让我有两种可以想到的可能性:
>一些暂时的条件导致创建大量的线程(但是在我们有机会做诊断之前,这些线程被丢弃)
内存分段是因为某些原因而杀死我们的有趣的是,最大的可分配块(每个VMMap是1MB) – 看起来不是很多…在另一台机器上的工作正常,最大的可分配块是470MB …
那么,有没有关于如何检查内存分段的指针?
编辑2:
我要承担:
操作系统进程空间限制:2GB
现代JVM需要250MB(这是一个很大的假设 – 我只是将链接文章中的内容翻了一番)
堆栈大小(默认Oracle):512KB
堆:512MB
PermGen :(完全不记得了,但肯定不到100MB,所以让我们用这个)
所以我有一个最坏的情况:(2GB – .25GB – .5GB – .1GB)/.005GB = 230线程
编辑3:
信息我应该原来包括:在此问题发生之前,应用程序运行正常(如24至48小时).该应用程序执行连续的后台处理,所以空闲时间很少.不确定是否重要
编辑4:
更多信息:从另一个失败中看VMMap,我看到本地堆耗尽.
堆的大小是1.2GB,只有59.8MB的承诺.
Java运行时间是这里的问题,也可能是本机资源未正确发布的一些问题?也许是一个没有被释放的内存映射文件?
我们使用内存映射文件,所以我会把重点放在那些.
编辑4:
我认为我已经将问题跟踪到一个例外,发生如下:
java.lang.OutOfMemoryError
at java.util.zip.Deflater.init(Native Method)
at java.util.zip.Deflater.(Unknown Source)
at java.util.zip.Deflater.(Unknown Source)
at java.util.zip.DeflaterOutputStream.(Unknown Source)
at java.util.zip.DeflaterOutputStream.(Unknown Source)
at ....
在一些非常少量的流(我现在有4个例子)我们正在放气,上述发生.而当发生这种情况时,VMMap会将进程的堆(不是JVM堆,而是实际的本机堆)高达2GB.一旦发生这种情况,一切都会崩溃.现在这是非常可重复的(运行相同的流进入deflater导致内存尖峰)
那么,我们可以看看JRE的zip库的问题吗?看起来很疯狂,认为是这样,但我真的很失落.
如果我使用完全相同的流并在不同的系统上运行(即使运行相同的JRE – 32位Java 7u45),我们也没有遇到问题.我完全卸载了JRE并重新安装了它,而没有任何改变的行为.