问题

在32k线程之后,我们在8GB RAM VM上获得了385264645(ps -eLF | grep -c java)

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

我们还尝试了OS stack size (ulimit -s)tweaking和max process(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

#1 热门回答(68 赞)

这不是内存问题,即使异常名称强烈建议,但操作系统资源问题。你的本机线程已用完,即操作系统将允许JVM使用多少个线程。

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

如果可能的话,你可以考虑在Executor的控制下重写使用Callable / Runnables。有许多标准的执行程序具有各种行为,你的代码可以轻松控制。

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


#2 热门回答(8 赞)

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

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


#3 热门回答(8 赞)

我在加载测试期间遇到了同样的问题,原因是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);`

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

在我的情况下,Jboss创建了太多线程来提供请求,但是所有线程都被阻止了。因此,JVM在线程和内存方面都很耗尽(每个线程都拥有内存,因为每个线程都被阻塞,所以内存不会被释放)。

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

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

原文链接