문제

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 커널은 프로세스를 스택에 할당된 메모리를 300MB로 제한하고 스택에 대해 스레드당 10MB로 제한하는 것으로 보이며 문제가 있을 수 있는 것처럼 보입니다(이상하고 가능성이 없어 보이지만).

이를 테스트하기 위해 "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)으로 업데이트하면 이 문제가 해결되었습니다.

다른 팁

봤어? 이 리소스?스레드 제한을 실행하여 최대 스레드 수를 찾을 수 있어야 하며 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