“java.lang.OutOfMemoryError:无法创build新的本地线程”

在32k线程后(ps -eLF | grep -c java),在8GB内存虚拟机上出现"java.lang.OutOfMemoryError : unable to create new native Thread

但是, "top" and "free -m" shows 50% free memory available 。 JDK是64位,并尝试使用HotSpot和JRockit.Server具有Linux 2.6.18

我们还尝试了OS stack size (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使用多less个线程。

这是一个不常见的问题,因为你很less需要那么多。 你有很多无条件的线程产生线程应该但不完成?

如果可能的话,您可以考虑在Executor的控制下重写使用Callable / Runnables。 有很多标准的执行者,你的代码可以很容易地控制各种行为。

(线程数量有限的原因有很多,但是从操作系统到操作系统有所不同)

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

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

我在加载testing时遇到了同样的问题,原因是JVM无法进一步创build新的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);

根本原因:当JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR(资源耗尽(意味着内存耗尽))或JVMTI_RESOURCE_EXHAUSTED_THREADS(线程已耗尽)时,JVM会抛出此exception。

在我的情况下,Jboss正在创build太多的线程来处理请求,但是所有的线程都被阻塞了。 因此,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) 

我build议也看看线程堆栈大小,看看你是否有更多的线程创build。 对于Linux OS上的64位VM, JRockit 1.5 / 1.6的默认线程堆栈大小为1 MB。 32K线程将需要大量的物理和虚拟内存来满足这个要求。

尝试将堆栈大小减less到512 KB作为起点,看看它是否有助于为您的应用程序创build更多的线程。 我还build议探索横向扩展,例如,跨多个物理或虚拟机器分割应用程序处理。

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

OutOfMemoryError:无法创build新的本地线程 – 问题揭秘

如果您的作业由于节点上的OutOfMemmory而失败,那么可以调整最大映射和缩减器的数量以及每个JVM的select。 mapred.child.java.opts(默认是200Xmx)通常必须根据您的数据节点特定的硬件来增加。

这个链接可能有帮助…请检查

你的JBossconfiguration有一些问题,/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m Xms和Xmx是限制你的JBoss内存使用情况,到configuration的值,所以从8Gb你有服务器只有Ussing 512M +一些额外的自己的目的,增加这个数字,记得留下一些免费的操作系统和其他的东西在那里运行,可能会让你运行,尽pipe代码不好。 如果可以的话,修复代码也不错。

您有机会面对java.lang.OutOfMemoryError: Unable to create new native thread无论何时JVM从OS请求新的线程,都java.lang.OutOfMemoryError: Unable to create new native thread 。 只要底层操作系统无法分配新的本地线程,就会抛出OutOfMemoryError。 原生线程的确切限制是非常依赖于平台的,因此build议通过运行类似于下面的链接示例的testing来找出这些限制。 但是,一般情况下,导致java.lang.OutOfMemoryError: Unable to create new native thread的情况经历了以下几个阶段:

  1. JVM中运行的应用程序请求新的Java线程
  2. JVM本地代码代理请求以创build一个新的本地线程到操作系统OS尝试创build一个新的本地线程需要内存分配给线程
  3. 操作系统将拒绝本地内存分配,原因是32位Java进程大小已经耗尽了其内存地址空间 – 例如(2-4)GB进程大小限制已被命中 – 或者操作系统的虚拟内存已经完全耗尽
  4. 抛出java.lang.OutOfMemoryError:无法创build新的本地线程错误。

参考: https : //plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread

我有同样的问题,因为在bash中使用top时没有显示的ghost进程。 这阻止了JVM产生更多的线程。

对于我来说,在使用jps列出所有的java进程(在你的shell中执行jps )时解决了这个问题,并使用kill -9 pid bash命令分别kill -9 pid了每个ghost进程。

这可能有助于某些情况。

我有这个相同的问题,原来是一个不正确的使用Java API。 我正在初始化一个批处理方法的build设者,这是不应该被初始化多次。

基本上我是这样做的:

 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) } 

首先,我不会责怪那么多OS / VM ..而是编写代码的开发人员创build了许multithreading 。 基本上在你的代码(或第三方) 某个地方, 很multithreading都是在没有控制的情况下创build的

仔细查看堆栈跟踪/代码并控制创build的线程数。 通常你的应用程序不需要大量的线程,如果这是一个不同的问题。