Red Hat Linux における Java シングル プロセス スレッドの制限が低い
質問
Java 1.6 (1.6.0_02 または 1.6.0_04) を使用して Red Hat Linux (カーネル バージョンは 2.4.21-37.ELsmp) を実行しているテスト マシンで問題が発生しています。問題は、単一スレッド グループ内に一定数のスレッドが作成されると、オペレーティング システムがそれ以上作成しようとしない、または作成できなくなることです。
C のスレッド制限プログラムでは約 1.5k のスレッドを作成できたため、これは Java のスレッド作成に特有のものと思われます。さらに、これは Java 1.4 JVM では起こりません...1.4k を超えるスレッドを作成できますが、それらは OS に関して明らかに異なる方法で処理されます。
この場合、切断されるスレッドの数はわずか 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 設定がこの問題を引き起こしているかについてのアイデアがあれば幸いです。
編集:で言及されたスレッド制限プログラムを実行する 台座, 、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) に更新すると、この問題が修正されました。
他のヒント
見ましたか このリソース?thread-limit を実行してスレッドの最大数を見つけることができ、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
.