&引用;java.lang.OutOfMemoryError:无法创建新的本机线程;

&引用;java.lang.OutOfMemoryError:无法创建新的本机线程;,java,out-of-memory,Java,Out Of Memory,我们得到了“java.lang.OutOfMemoryError:在32k个线程(ps-eLF | grep-cJava)之后,无法在8GB RAM虚拟机上创建新的本机线程 但是,“top”和“free-m”显示可用内存的50%。JDk是64位的,在HotSpot和JRockit上都有尝试 我们还尝试了OS堆栈大小(ulimit-s)调整和最大进程(ulimit-u)限制,limit.conf增加,但都没有成功 我们还尝试了几乎所有可能的堆大小组合,保持低、高等 我们用来运行应用程序的脚本是 /

我们得到了
“java.lang.OutOfMemoryError:在32k个线程(ps-eLF | grep-cJava)之后,无法在8GB RAM虚拟机上创建新的本机线程

但是,
“top”和“free-m”显示可用内存的50%
。JDk是64位的,在HotSpot和JRockit上都有尝试

我们还尝试了
OS堆栈大小(ulimit-s)
调整和最大进程(ulimit-u)限制,limit.conf增加,但都没有成功

我们还尝试了几乎所有可能的堆大小组合,保持低、高等

我们用来运行应用程序的脚本是

/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties
谢谢你的回复

我们尝试过编辑/etc/security/limits.conf和ulimit,但仍然是一样的

[root@jboss02 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 72192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 72192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

很可能您的操作系统不允许您尝试创建的线程数量,或者您在JVM中遇到了一些限制。特别是如果是32k这样的整数,那么一种或另一种限制很可能是罪魁祸首


你确定你真的需要32k线程吗?大多数现代语言对可重用线程池都有某种支持——我相信Java也有一些支持(如用户Jesper提到的
ExecutorService
)。也许您可以从这样的池中请求线程,而不是手动创建新的线程。

如果您的作业由于节点上的OutOfMemory而失败,您可以查看最大映射和还原器的数量以及每个线程的JVM选项。通常必须根据特定于数据节点的硬件增加mapred.child.java.opts(默认值为200Xmx)


可能会有帮助。。。请检查

这不是一个内存问题,尽管异常名称强烈暗示这是一个内存问题,而是一个操作系统资源问题。您正在耗尽本机线程,即操作系统将允许JVM使用多少线程

这是一个不常见的问题,因为您很少需要这么多。你是否有很多无条件的线程繁殖,这些线程应该完成,但没有完成

如果可能的话,你可以考虑在执行器的控制下重写使用可调用的Runnables。有很多标准的执行器,它们具有各种行为,您的代码可以轻松控制这些行为


(线程数量有限的原因有很多,但它们因操作系统而异)

我还建议查看线程堆栈大小,看看是否创建了更多线程。Linux操作系统上64位VM的默认线程堆栈大小为1 MB。32K线程将需要大量的物理和虚拟内存来满足这一要求

尝试将堆栈大小减少到512 KB作为起点,看看它是否有助于为应用程序创建更多线程。我还建议探索水平扩展,例如在更多物理或虚拟机上拆分应用程序处理

当使用64位虚拟机时,真正的限制将取决于操作系统物理和虚拟内存可用性以及操作系统调优参数,如ulimitc。我还推荐以下文章作为参考:


首先,我不会责怪操作系统/虚拟机太多。。而是编写代码来创建大量线程的开发人员。 基本上,在代码的某个地方(或第三方)很多线程都是在没有控制的情况下创建的


仔细检查stacktraces/代码并控制创建的线程数。通常情况下,你的应用程序不需要大量线程,如果需要,那是另一个问题。

你的JBoss配置有一些问题, /opt/jrockit-jdk1.6/bin/java-Xms512m-Xmx512m Xms和Xmx将您的JBoss内存使用限制为配置的值,因此从8Gb开始,服务器只使用512M+一些额外的内存用于自己的目的,增加这个数字,记住为运行在那里的操作系统和其他东西留出一些空闲空间,尽管代码不太令人满意,但您可能会让它运行。
如果可以的话,修复代码也很好。

我在负载测试期间遇到了相同的问题,原因是JVM无法进一步创建新的Java线程。下面是JVM源代码

if (native_thread->osthread() == NULL) {    
// No one should hold a reference to the 'native_thread'.    
    delete native_thread;   
if (JvmtiExport::should_post_resource_exhausted()) {      
    JvmtiExport::post_resource_exhausted(        
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | 
        JVMTI_RESOURCE_EXHAUSTED_THREADS, 
        "unable to create new native thread");    
    } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread");  
} Thread::start(native_thread);`
根本原因:JVM在 JVMTI_资源耗尽_OOM_错误(资源耗尽(表示内存 耗尽)或JVMTI_资源_耗尽_线程(线程耗尽)

在我的例子中,Jboss创建了太多的线程来处理请求,但是所有的线程都被阻塞了。正因为如此,JVM的线程和内存都会耗尽(每个线程都拥有内存,而内存不会被释放,因为每个线程都被阻塞)

分析了观察到的java线程转储,其中一个方法阻塞了近61K个线程,这导致了此问题。下面是线程转储的一部分

"SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000]
   java.lang.Thread.State: BLOCKED (on object monitor)

我也遇到了同样的问题,结果证明这是对JavaAPI的不当使用。我在批处理方法中初始化一个构建器,该方法不应该多次初始化

基本上我是在做这样的事情:

for (batch in batches) {
    process_batch(batch)
}

def process_batch(batch) {
    var client = TransportClient.builder().build()
    client.processList(batch)
}
当我应该这样做的时候:

for (batch in batches) {
    var client = TransportClient.builder().build()
    process_batch(batch, client)
}

def process_batch(batch, client) {
    client.processList(batch)
}

您有机会遇到
java.lang.OutOfMemoryError:每当JVM从操作系统请求新线程时,都无法创建新的本机线程。每当底层操作系统无法分配新的本机线程时,就会抛出此OutOfMemoryError。本机线程的确切限制非常依赖于平台,因此建议通过运行类似于下面链接示例的测试来找出这些限制。但是,通常情况下,导致
java.lang.OutOfMemoryError:无法创建新的本机线程
的情况会经历以下阶段:

  • 一个新的Java线程由运行在 虚拟机
  • JVM本机代码代理创建新本机代码的请求 线程到操作系统操作系统尝试创建一个新的本机线程 需要为线程分配内存
  • ps huH