问题
在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)