创建<100个线程时的Java`OutOfMemoryError`

由于这个错误,我一直在阅读和测试并在墙上撞了一天超过一天。

我在一个名为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之间)。 服务器有24 GB的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

UPDATE2:放弃perl Forks::Super库并从bash运行客户端让我在服务器与OOME崩溃之前最多可以运行34个线程,因此运行多个客户端肯定会对服务器产生影响,但同时我仍然应该能够一次运行超过34个(如果一个客户端计算68个)java线程。 哪些系统资源阻止了更multithreading的创建(即我应该在哪里寻找生猪)? 当所有内容(客户端,服务器,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 

UPDATE3:下面的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 

您可以限制max user processes ,以了解您的限制使用:

 ulimit -u 

要更改限制:

/etc/security/limits.conf设置:

 user soft nproc [your_val] user hard nproc [your_val] 

如果查看此链接不够,您可能需要添加其他配置。

注意:OP在fedora和centos中发现了这个错误报告 ,解释了编辑/etc/security/limits.conf的局限性。

您的问题可能与JVM无法为新线程分配堆栈内存有关。 具有讽刺意味的是,这个问题可以通过减少堆空间(-Xmx)和堆栈空间(-Xss)来解决。 例如,请查看此处以获得一个很好的解释: http : //www.blogsoncloud.com/jsp/techSols/java-lang-OutOfMemoryError-unable-to-create-new-native-thread.jsp

它不会丢失新线程的内存,它缺少实际的线程。 系统可能会阻止你:用户可以创建的线程数量有限制。 您可以这样查询:

 cat /proc/sys/kernel/threads-max 

请注意,您可能会受到同一台计算机上其他进程的影响,您也可以创建多个线程。 您可能会发现此问题很有用: Linux中每个进程的最大线程数?

只是为了澄清:

您向Thread提供ServerSocket 。 你把数据发送到那个Socket吗? 也许你在Thread-Context中存储了很多数据。 查找模式,在一个byte[]存储Streamdata。