由于这个错误,我已经阅读、测试并且苦思冥想了一整天。我的一个名叫Listener
的Java类中有下面这段代码:
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
boolean listening = true;
int count = 0;
while (listening) {
Runnable worker;
try {
worker = new ServerThread(serverSocket.accept()); // this is line 254
executor.execute(worker);
count++;
logger.info("{} threads started", count);
} catch (Exception e1){
//...
}
}
我一直在调整JVM设置-Xmx
(从1到15G不等)和-Xss
(从104k到512M不等)。服务器有24GB的RAM,但还必须运行支持程序的数据库。
创建了2-20个线程后(程序中其他地方还有几十个线程),我会收到错误消息。
Exception in thread "Thread-0" java.lang.OutOfMemoryError: unable to create new native thread
at java.lang.Thread.start0(Native Method)
at java.lang.Thread.start(Thread.java:657)
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:943)
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1325)
at xxx.Listener.run(Listener.java:254)
$java -version
的输出结果如下:
java version "1.6.0_24"
OpenJDK Runtime Environment (IcedTea6 1.11.1) (fedora-65.1.11.1.fc16-x86_64)
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode)
当这种情况发生时,系统上始终有大量的空闲内存,并且其他程序继续正常执行。是什么导致Java认为没有足够的内存来创建新线程?更新: 也许这比我想象的要大 - 我在使用^C时(仅此一次)遇到了此错误:
OpenJDK 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated
当我试图关闭客户端时(也是用Java编写,并在同一服务器上运行,它是一个单线程,读取文件并通过套接字将其发送到服务器),情况也是如此,因此绝对存在限制超出JVM导致干扰另一个,但如果我仍然有免费的内存并且完全没有使用交换?服务器-Xmx1G -Xss104k 客户端-Xmx10M
更新2:放弃perl Forks::Super库,从bash运行客户端,在服务器崩溃并出现OOME之前可以达到34个线程,因此运行多个客户端肯定会影响服务器,但同时我仍然能够同时运行超过34个(如果将客户端计算在内则为68)java线程。哪些系统资源阻止了更多线程的创建(即我应该在哪里查找占用资源)?当所有内容(客户端、服务器、GC...)同时耗尽内存时,top
显示我的CPU和内存使用情况:
Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 24681040k total, 1029420k used, 23651620k free, 30648k buffers
Swap: 26836988k total, 0k used, 26836988k free, 453620k cached
更新3:下面的 hs_error 日志是否表明我的 Java 不是 64 位的?
# There is insufficient memory for the Java Runtime Environment to continue.
# Cannot create GC thread. Out of system resources.
# Possible reasons:
# The system is out of physical RAM or swap space
# In 32 bit mode, the process size limit was hit
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Use 64 bit Java on a 64 bit OS
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# This output file may be truncated or incomplete.
#
# JRE version: 6.0_24-b24
# Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops)
# Derivative: IcedTea6 1.11.1
# Distribution: Fedora release 16 (Verne), package fedora-65.1.11.1.fc16-x86_64
ulimit -u
命令会返回最大用户进程数,也许你的限制就在这里。 - alain.janinmulimit -u
返回1024 - 这可能是问题所在。怎样更改这个设置呢? - kaz/etc/security/limits.conf
中设置user soft nproc [your_val]
和user hard nproc [your_val]
。如果不够的话,您可能需要添加一些其他配置,请参阅此链接http://directory.fedoraproject.org/wiki/Performance_Tuning。 - alain.janinm/etc/security/limits.conf
的限制。链接 @alain.janinm:更改 nproc 值的此解决方案确实解决了我的问题。谢谢。 - kaz