我在使用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程序仅创建线程直到出现错误,然后打印其创建的线程数。错误是
java.lang.OutOfMemoryError:无法创建新的本机线程
这似乎不受其他进程或用户正在使用的线程数或系统当时正在使用的内存总量等因素的影响。像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设置的任何想法将不胜感激。
编辑 :运行由提到的线程限制程序的底座,也没有失败,直到它试图创建第一千五百二十九线程。
使用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模型。
使用NPTL线程将内核更新为较新的版本(2.6.something)可以解决此问题。