Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/397.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无法创建新的本机线程错误-但使用的线程很少_Java_Multithreading_Memory - Fatal编程技术网

Java 无法创建新的本机线程错误-但使用的线程很少

Java 无法创建新的本机线程错误-但使用的线程很少,java,multithreading,memory,Java,Multithreading,Memory,我们有一个广泛部署的应用程序(数百个运行它的工作站)。在一个站点(而且只有一个站点—我们的产品广泛部署到许多环境),我们随机得到以下错误: java.lang.OutOfMemoryError:无法创建新的本机线程 位于java.lang.Thread.start0(本机方法) 位于java.lang.Thread.start(未知源) 操作系统为64位Windows 7 我们在32位JVM(1.7.0_45)中运行 使用Windows任务管理器,我可以看到进程有39个本机线程(不是很多),因此

我们有一个广泛部署的应用程序(数百个运行它的工作站)。在一个站点(而且只有一个站点—我们的产品广泛部署到许多环境),我们随机得到以下错误:

java.lang.OutOfMemoryError:无法创建新的本机线程 位于java.lang.Thread.start0(本机方法) 位于java.lang.Thread.start(未知源)

操作系统为64位Windows 7 我们在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启动的

我们的进程显示内存使用量(在任务管理器中)为597744K

工作站有8GB的RAM,其中只使用了3.8-4.0GB(我知道,32位进程无法访问所有这些,但仍然有很多)

使用VMMap,堆栈大小为49920kb,提交2284k

该进程显示5358KB空闲,空闲列表中最大的可分配块大小为1024K

我使用了资源监视器,它显示提交(KB)为630428,工作集(KB)为676996,可共享(KB)为79252,私有(KB)为597744

我完全不知道这里发生了什么事。我已经读了很多关于这方面的文章,听起来在一些Linux系统上,每个用户的线程限制可能会导致问题(但这不是Linux,其他文章中描述的问题通常是需要数千个线程——这里肯定不是我们的情况)

如果我们的堆真的很大,我可以看出会占用线程可用的空间,但500MB似乎是一个非常合理的小堆(特别是对于具有8GB RAM的工作站)

所以我已经用尽了所有我知道要做的事情——有没有人对这里可能发生的事情有任何额外的建议

编辑1:

我发现这篇有趣的文章:

他们认为堆栈大小可能是问题所在

本文:-提供了一个指向Oracle文档的链接,说明默认堆栈大小为512KB。因此,如果我的应用程序有大约40个线程,我们将看到20MB的堆栈。500MB堆。对于32位Java进程来说,这一切似乎都在正常范围内

因此,我可以想到两种可能性:

  • 某些瞬态条件导致创建大量线程(但在我们有机会进行诊断之前,这些线程已被丢弃)
  • 由于某种原因,内存分割正在杀死我们。有趣的是,最大的可分配块(每个VMMap为1MB)-看起来不太像。。。在另一台工作正常的机器上,最大的可分配块是470MB
  • 那么,关于如何检查内存分段,有什么建议吗

    编辑2:

    @mikhael()链接的文章给出了32位JVM上允许的线程数的一些粗略计算

    我将假设:

    操作系统进程空间限制: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.<init>(Unknown Source)
        at java.util.zip.Deflater.<init>(Unknown Source)
        at java.util.zip.DeflaterOutputStream.<init>(Unknown Source)
        at java.util.zip.DeflaterOutputStream.<init>(Unknown Source)
        at ....
    
    java.lang.OutOfMemoryError
    位于java.util.zip.Deflater.init(本机方法)
    位于java.util.zip.Deflater。(未知源)
    位于java.util.zip.Deflater。(未知源)
    位于java.util.zip.DeflaterOutputStream。(未知源)
    位于java.util.zip.DeflaterOutputStream。(未知源)
    在
    
    在一些非常小的流(我现在有4个例子)上,我们正在放气,上面发生了。当发生这种情况时,VMMap会将进程堆(不是JVM堆,而是实际的本机堆)的峰值增加到2GB。一旦发生这种情况,一切都会分崩离析。这现在是非常可重复的(将相同的流运行到deflater会导致内存峰值)

    那么,我们是否在考虑JRE的zip库的问题?这么想似乎很疯狂,但我真的不知所措


    如果我使用完全相同的流并在不同的系统上运行它(即使运行相同的JRE-32位,Java7U45),我们就不会遇到问题。我已经完全卸载了JRE并重新安装了它,行为没有任何变化。

    我怀疑,尽管很难证明,您遇到了32位内存分配问题

    线程分配为nati