我在使用Java 1.6(1.6.0_02或1.6.0_04)运行Red Hat Linux(内核版本为2.4.21-37.ELsmp)的测试计算机上遇到问题。问题是,一旦在单个线程组中创建了一定数量的线程,操作系统就不愿意或不能再创建了。

这似乎特定于Java创建线程,因为C线程限制程序能够创建大约1.5k线程。此外,Java 1.4 JVM不会发生这种情况......它可以创建超过1.4k的线程,但显然它们在操作系统方面的处理方式不同。

在这种情况下,它切断的线程数仅为29个线程。这可以通过一个简单的Java程序来测试,该程序只是创建线程,直到它出现错误,然后打印它创建的线程数。错误是

java.lang.OutOfMemoryError: unable to create new native thread

这似乎不受其他进程或用户使用的线程数或系统当时使用的内存总量等因素的影响。像Xms,Xmx和Xss这样的JVM设置似乎也没有改变任何东西(考虑到问题似乎与本机OS线程创建有关,这是预期的。)

“ulimit -a”的输出。如下:

core file size        (blocks, -c) 0
data seg size         (kbytes, -d) unlimited
file size             (blocks, -f) unlimited
max locked memory     (kbytes, -l) 4
max memory size       (kbytes, -m) unlimited
open files                    (-n) 1024
pipe size          (512 bytes, -p) 8
stack size            (kbytes, -s) 10240
cpu time             (seconds, -t) unlimited
max user processes            (-u) 7168
virtual memory        (kbytes, -v) unlimited

用户进程限制似乎不是问题。搜索可能出错的信息并没有太多,但这篇文章似乎表明至少有一些Red Hat内核将进程限制为为堆栈分配的300 MB内存,并且每个线程10 MB用于堆栈,似乎问题可能存在(尽管它似乎很奇怪且不太可能孔)。

我尝试用“ulimit -s”更改堆栈大小。要对此进行测试,但除了10240和JVM之外的任何值都不会以错误:

开头
Error occurred during initialization of VM
Cannot create VM thread. Out of system resources.

我通常可以绕过Linux,但我真的不太了解系统配置,而且我无法找到任何具体解决这种情况的方法。关于什么系统或JVM设置可能导致这种情况的任何想法将不胜感激。

编辑:运行 plinth ,在尝试创建第1529个帖子之前没有失败。

使用1.4 JVM时也没有出现此问题(确实发生在1.6.0_02和1.6.0_04 JVM上,目前无法使用1.5 JVM进行测试)。

我正在使用的线程测试代码如下:

public class ThreadTest {

   public static void main(String[] pArgs) throws Exception {

      try {
         // keep spawning new threads forever
         while (true) {
            new TestThread().start();
         }
      }
      // when out of memory error is reached, print out the number of
      // successful threads spawned and exit
      catch ( OutOfMemoryError e ) {
         System.out.println(TestThread.CREATE_COUNT);
         System.exit(-1);
      }
   }

   static class TestThread extends Thread {
      private static int CREATE_COUNT = 0;
      public TestThread() {
         CREATE_COUNT++;
      }
      // make the thread wait for eternity after being spawned
      public void run() {
         try {
            sleep(Integer.MAX_VALUE);
         }
         // even if there is an interruption, dont do anything
         catch (InterruptedException e) {
         }
      }
   }
}

如果你使用1.4 JVM运行它,当它无法创建更多线程并且需要kill -9(至少它对我来说)时会挂起。

更多编辑

事实证明,遇到问题的系统是使用LinuxThreads线程模型,而另一个工作正常的系统是使用NPTL模型。

有帮助吗?

解决方案 2

使用NPTL线程将内核更新为更新版本(2.6.something)。

其他提示

您是否查看了此资源? 它声明你应该能够运行线程限制来找到最大线程数,并且可以通过编译glibc来调整它。

这是使用Ubuntu Linux(1GB RAM)

dsm@localhost:~$ javac ThreadTest.java 
dsm@localhost:~$ java ThreadTest 
8113
dsm@localhost:~$ java -version
java version "1.6.0_07"
Java(TM) SE Runtime Environment (build 1.6.0_07-b06)
Java HotSpot(TM) Client VM (build 10.0-b23, mixed mode, sharing)
dsm@localhost:~$ 

你可以试试JRockit JVM吗? IIRC,它有一个不同于Sun JVM库存的线程模型。

/etc/security/limits.d/90-nproc.conf 中的设置可能会覆盖您的 /etc/security/limits.conf 设置。这可能导致系统以 ulimit -u 中显示的不同方式执行。

https://bugzilla.redhat.com/show_bug.cgi?id=823030

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top