“java.lang.OutOfMemoryError : 새 네이티브 스레드를 만들 수 없습니다.”


124

"java.lang.OutOfMemoryError : unable to create new native Thread32k 스레드 후에 8GB RAM VM 에서 " 가 발생 합니다 (ps -eLF | grep -c java).

그러나 "top" and "free -m" shows 50% free memory available. JDk는 64 비트이며 HotSpot과 JRockit 모두에서 시도되었습니다. Server에는 Linux 2.6.18이 있습니다.

우리는 또한 OS stack size (ulimit -s)조정 및 최대 프로세스 (ulimit -u) 제한, limit.conf 증가를 시도했지만 모두 헛된 것입니다.

또한 가능한 거의 모든 힙 크기 조합을 시도하여 낮음, 높음 등으로 유지했습니다.

응용 프로그램을 실행하는 데 사용하는 스크립트는

/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties

답장을 보내 주셔서 감사합니다.

/etc/security/limits.conf 및 ulimit 편집을 시도했지만 여전히 동일합니다.

[root@jboss02 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 72192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 72192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

11
운영 체제에는 만들 수있는 스레드 수에 제한이 있습니다. 32k 이상의 스레드를 생성하는 이유는 무엇입니까? 시스템에 수천 개의 프로세서 코어가 없을 가능성이 높으므로 스레드를 너무 많이 생성하는 것은 유용하지 않습니다. ExecutorService대신 스레드 풀 ( )을 사용하십시오.
Jesper 2013 년

답장을 보내 주셔서 감사합니다. 우리는 오픈 소스 라이브러리를 사용하고 있으며이를로드 테스트하려고합니다. 오픈 소스 라이브러리는 너무 많은 스레드를 생성합니다. 그러나 내가 이해하지 못하는 것은 "상단"이 50 % 여유 메모리를 표시 할 때 OutOfMemory 오류가 발생하는 이유입니다.
Deepak Tewani 2013 년

ICE4j 라이브러리에서 사용하는 오픈 소스 라이브러리
Deepak Tewani 2013 년

11
OutOfMemoryError가 반드시 힙 공간 또는 "일반"RAM이 소진 되었음을 의미 하지는 않습니다 . 이 경우 실패는 OS에 추가 스레드를 할당 할 리소스가 없기 때문이라는 것이 분명합니다. 50 % 여유 메모리를 갖는 것은이 특정 오류와 관련이 없습니다.
Andrzej Doyle

1
새 스레드를 만드는 데 필요한 기타 리소스는 무엇입니까? 우리는 RAM을 늘리면 더 많은 스레드를 만들 수 있다는 인상을 받았습니다. 친절하게 우리를 안내하십시오
Deepak Tewani 2013 년

답변:


80

이것은 예외 이름이 강력하게 암시하더라도 메모리 문제가 아니라 운영 체제 리소스 문제입니다. 원시 스레드가 부족합니다. 즉, 운영 체제가 JVM에서 사용할 수있는 스레드 수입니다.

그렇게 많이 필요하지 않기 때문에 이것은 드문 문제입니다. 스레드가 끝나야하지만 끝나지 않는 곳에서 무조건적인 스레드 스폰이 많이 있습니까?

가능하다면 Executor의 제어하에 Callable / Runnables를 사용하여 다시 작성하는 것을 고려할 수 있습니다. 코드에서 쉽게 제어 할 수있는 다양한 동작을 가진 많은 표준 실행기가 있습니다.

(스레드 수가 제한된 이유는 여러 가지가 있지만 운영 체제마다 다릅니다.)


답장을 보내 주셔서 감사합니다. 우리는 오픈 소스 라이브러리 ICE4j를 사용하고 있으며이를로드 테스트하려고합니다. 서버에 50 %의 메모리가 남아 있음을 알게되면 OS의 스레드 제한을 늘릴 수 없습니다.
Deepak Tewani 2013 년

그럴 수도 있지만 그렇게된다면 도움이되지 않을 것 같습니다. 부하 테스트시 리소스가 부족한 경우 애플리케이션에서 일어나는 일을 제어 할 수 있어야합니다. 한 번에 32000 개의 스레드가 활성화 된 이유는 무엇입니까?
Thorbjørn Ravn Andersen

UDP 소켓에서 데이터를 읽고 쓰는 데 32K 스레드를 사용하는 11K 클라이언트를 만들고 있습니다. 이 32K 스레드 중 10K 스레드는 소켓을 열린 상태로 유지하는 데 사용되는
활성

이 문제는 현대 웹 서버에서 해결되었다고 생각합니다. 또한 udp는 패킷을 잃을 수 있습니다-웹 서버를 사용하지 않는 이유가 있습니까?
Thorbjørn Ravn Andersen

7
OutOfMemory 예외는 OutOfResources로 이름이 지정되어야하기 때문입니다. 운영 체제는 필요한 리소스를 제공 할 수 없습니다. (그리고 내가 ice4j를 몰랐다는 것이 밝혀졌습니다)
Thorbjørn Ravn Andersen

14

부하 테스트 중에 동일한 문제가 발생했는데 그 이유는 JVM이 새 Java 스레드를 더 이상 만들 수 없기 때문입니다. 아래는 JVM 소스 코드입니다.

if (native_thread->osthread() == NULL) {    
// No one should hold a reference to the 'native_thread'.    
    delete native_thread;   
if (JvmtiExport::should_post_resource_exhausted()) {      
    JvmtiExport::post_resource_exhausted(        
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | 
        JVMTI_RESOURCE_EXHAUSTED_THREADS, 
        "unable to create new native thread");    
    } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread");  
} Thread::start(native_thread);`

근본 원인 : JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR (자원 고갈 (메모리 고갈 의미)) 또는 JVMTI_RESOURCE_EXHAUSTED_THREADS (스레드 고갈) 인 경우 JVM에서이 예외가 발생합니다.

제 경우에는 Jboss가 요청을 처리하기 위해 너무 많은 스레드를 생성하고 있지만 모든 스레드가 차단됩니다. 이로 인해 JVM은 메모리와 함께 스레드와 함께 소모됩니다 (각 스레드는 각 스레드가 차단되기 때문에 해제되지 않는 memory를 보유합니다).

분석 된 자바 스레드 덤프에서 거의 61K 스레드가 우리의 방법 중 하나에 의해 차단되어이 문제를 일으키는 것으로 나타났습니다. 아래는 스레드 덤프 부분입니다.

"SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000]
   java.lang.Thread.State: BLOCKED (on object monitor)

메소드 차단은 어땠습니까? 돌아 오지 않나요?
Thorbjørn Ravn Andersen

8

OS가 생성하려는 스레드 수를 허용하지 않거나 JVM에서 일부 제한에 도달 할 수 있습니다. 특히 32k와 같은 라운드 수인 경우 한 종류 또는 다른 종류의 제한이 원인 일 가능성이 높습니다.

정말로 32k 스레드가 필요합니까? 대부분의 현대 언어는 재사용 가능한 스레드 풀에 대해 일종의 지원을 제공합니다. Java도 ExecutorService제스퍼 사용자가 언급했듯이. 수동으로 새 풀을 만드는 대신 이러한 풀에서 스레드를 요청할 수 있습니다.


1
답장을 보내 주셔서 감사합니다. 우리는 오픈 소스 라이브러리 ICE4j를 사용하고 있으며로드 테스트를 시도하고 있습니다. 서버에 50 %의 메모리가 남아 있음을 알게되면 OS의 스레드 제한을 늘릴 수 없습니다.
Deepak Tewani 2013 년

1
UDP 소켓에서 데이터를 읽고 쓰는 데 32K 스레드를 사용하는 11K 클라이언트를 만들고 있습니다. 이 32K 스레드 중 10K 스레드는 소켓을 열린 상태로 유지하는 데 사용되는
활성

7

스레드 스택 크기도 살펴보고 더 많은 스레드가 생성되는지 확인하는 것이 좋습니다. JRockit 1.5 / 1.6 의 기본 스레드 스택 크기 는 Linux OS에서 64 비트 VM의 경우 1MB입니다. 32K 스레드는이 요구 사항을 충족하기 위해 상당한 양의 실제 및 가상 메모리가 필요합니다.

시작점으로 스택 크기를 512KB 로 줄이고 애플리케이션에 대한 더 많은 스레드를 만드는 데 도움이되는지 확인하십시오. 또한 수평 적 확장 (예 : 더 많은 물리적 또는 가상 머신으로 애플리케이션 처리 분할)을 탐색하는 것이 좋습니다.

64 비트 VM을 사용할 때 실제 제한은 OS 물리적 및 가상 메모리 가용성과 ulimitc와 같은 OS 튜닝 매개 변수에 따라 달라집니다. 또한 다음 기사를 참조로 권장합니다.

OutOfMemoryError : 새 원시 스레드를 만들 수 없음 – 문제가 설명 됨


5

jvm이 systemd를 통해 시작되면 일부 Linux OS에서 프로세스 당 maxTasks 제한 (실제로 작업은 스레드를 의미 함)이있을 수 있습니다.

"서비스 상태"를 실행하여이를 확인하고 maxTasks 제한이 있는지 확인할 수 있습니다. 있는 경우 /etc/systemd/system.conf를 편집하고 구성을 추가하여 제거 할 수 있습니다. DefaultTasksMax = infinity


3

bash에서 top을 사용할 때 표시되지 않는 고스트 프로세스로 인해 동일한 문제가 발생했습니다. 이로 인해 JVM이 더 많은 스레드를 생성하지 못했습니다.

나를 위해 모든 자바 프로세스를 jps ( jps셸에서 실행) 로 나열하고 kill -9 pid각 고스트 프로세스에 대해 bash 명령을 사용하여 개별적으로 죽일 때 해결 되었습니다 .

이것은 일부 시나리오에서 도움이 될 수 있습니다.


2

java.lang.OutOfMemoryError: Unable to create new native threadJVM이 OS에서 새 스레드를 요청할 때마다 직면 할 수있는 기회가 있습니다. 기본 OS가 새 원시 스레드를 할당 할 수 없을 때마다이 OutOfMemoryError가 발생합니다. 네이티브 스레드의 정확한 제한은 플랫폼에 따라 매우 다르므로 아래 링크 예제와 유사한 테스트를 실행하여 이러한 제한을 알아내는 것이 좋습니다. 그러나 일반적으로 원인 java.lang.OutOfMemoryError: Unable to create new native thread이 되는 상황 은 다음 단계를 거칩니다.

  1. JVM 내에서 실행되는 응용 프로그램에서 새 Java 스레드를 요청합니다.
  2. JVM 네이티브 코드는 OS에 대한 새 네이티브 스레드를 생성하도록 요청을 프록시합니다. OS는 스레드에 메모리를 할당해야하는 새 네이티브 스레드를 생성하려고합니다.
  3. OS는 32 비트 Java 프로세스 크기가 메모리 주소 공간을 고갈 시켰거나 (예 : (2-4) GB 프로세스 크기 제한에 도달 했음) 또는 OS의 가상 메모리가 완전히 고갈 되었기 때문에 기본 메모리 할당을 거부합니다.
  4. java.lang.OutOfMemoryError : 새 원시 스레드를 작성할 수 없음 오류가 발생합니다.

참조 : https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread


2

스레드를 생성하는 프로세스를 찾으려면 다음을 시도하십시오.

ps huH

일반적으로 출력을 파일로 리디렉션하고 파일을 오프라인으로 분석합니다 (각 프로세스의 스레드 수가 예상대로인지 여부).


1

노드의 OutOfMemmory로 인해 작업이 실패하는 경우 최대 맵 및 감속기 수를 tweek 할 수 있으며 JVM이 각각을 선택할 수 있습니다. mapred.child.java.opts (기본값은 200Xmx)는 일반적으로 데이터 노드 특정 하드웨어에 따라 늘려야합니다.

이 링크 가 도움 될 수 있습니다 ... pls 확인


1
우리는 이미 그 링크에 주어진 변화를 시도했습니다. 그러나 결과는 동일합니다 :(
Deepak Tewani

1

JBoss 구성에 몇 가지 문제가 있습니다. /opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m Xms 및 Xmx는 JBoss 메모리 사용량을 구성된 값으로 제한하므로 8Gb에서 서버는 512M 만 사용합니다. + 자신의 목적을 위해 추가하고, 그 수를 늘리고, OS 및 거기에서 실행되는 다른 물건을 위해 일부를 남겨 두는 것을 잊지 마십시오. 불미스러운 코드에도 불구하고 실행할 수 있습니다. 가능하다면 코드를 수정하는 것도 좋을 것입니다.


1

이 오류는 다음 두 가지 이유로 인해 나타날 수 있습니다.

  • 새 스레드를 수용 할 공간이 메모리에 없습니다.

  • 스레드 수가 운영 체제 한계를 초과합니다.

스레드 수가 Java 프로세스의 제한을 초과했는지 의심됩니다.

따라서 가능성이 문제는 기억 때문일 수 있습니다. 고려해야 할 한 가지 사항은

스레드는 JVM 힙 내에 생성되지 않습니다. JVM 힙 외부에서 생성됩니다. 따라서 RAM에 남은 공간이 적 으면 JVM 힙 할당 후 응용 프로그램이 "java.lang.OutOfMemoryError : 새 원시 스레드를 만들 수 없습니다"라는 메시지가 표시됩니다.

가능한 해결책은 힙 메모리를 줄이거 나 전체 램 크기를 늘리는 것입니다.


0

나는 이와 동일한 문제가 있었고 Java API의 부적절한 사용으로 판명되었습니다. 두 번 이상 초기화되지 않아야하는 일괄 처리 방법으로 빌더를 초기화하고있었습니다.

기본적으로 다음과 같은 작업을했습니다.

for (batch in batches) {
    process_batch(batch)
}

def process_batch(batch) {
    var client = TransportClient.builder().build()
    client.processList(batch)
}

내가 이것을해야 할 때 :

for (batch in batches) {
    var client = TransportClient.builder().build()
    process_batch(batch, client)
}

def process_batch(batch, client) {
    client.processList(batch)
}

-4

우선 저는 OS / VM을 그렇게 탓하지 않을 것입니다. 오히려 너무 많은 Thread 를 생성하는 코드를 작성한 개발자입니다 . 기본적으로 코드 (또는 타사) 어딘가에 제어없이 많은 스레드가 생성됩니다 .

스택 추적 / 코드를주의 깊게 검토하고 생성되는 스레드 수를 제어합니다. 일반적으로 앱에는 많은 양의 스레드가 필요하지 않아야합니다. 만약 필요하다면 다른 문제입니다.


10
이것은 질문에 대한 해결책이 아닙니다.
ftrujillo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.