"Java.lang.OutOfMemoryError: yeni yerel İş Parçacığı oluşturulamıyor"


124

"java.lang.OutOfMemoryError : unable to create new native Thread32k iş parçacığından (ps -eLF | grep -c java) sonra 8GB RAM VM " elde ediyoruz "

Ancak "top" and "free -m" shows 50% free memory available. JDk 64 bittir ve hem HotSpot hem de JRockit ile denenmiştir.Sunucu Linux 2.6.18'e sahiptir.

Ayrıca OS stack size (ulimit -s)tweaking ve max process (ulimit -u) limitleri, limit.conf artışı ama hepsi boşuna denedik.

Ayrıca, neredeyse tüm olası yığın boyutu kombinasyonlarını denedik, düşük, yüksek vb.

Uygulamayı çalıştırmak için kullandığımız komut dosyası

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

Cevap için teşekkürler.

/Etc/security/limits.conf ve ulimit'i düzenlemeyi denedik ama yine de aynı

[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
İşletim sistemleri, oluşturabileceğiniz iş parçacığı sayısı konusunda sınırlamalara sahiptir. Neden 32 binden fazla iş parçacığı oluşturuyorsunuz? Sisteminizde büyük olasılıkla binlerce işlemci çekirdeği bulunmadığından bu kadar çok iş parçacığı oluşturmak kullanışlı değildir. ExecutorServiceBunun yerine bir iş parçacığı havuzu ( ) kullanın.
Jesper

Cevap için teşekkürler. Açık kaynak bir kütüphane kullanıyoruz ve bunu test etmeye çalışıyoruz. Herhangi bir açık kaynak kitaplığı çok fazla iş parçacığı oluşturuyor. Ama anlamadığım şey, "top"% 50 boş bellek gösterdiğinde, neden OutOfMemory Hatası.
Deepak Tewani

ICE4j Library'de kullandığımız açık kaynak kütüphanesi
Deepak Tewani

11
OutOfMemoryError yapar olmayan ortalama yığın alanı ya da "genel" RAM zorunlu tükenmiş. Bu durumda, hatanın, işletim sisteminin fazladan bir iş parçacığı tahsis edecek kaynaklara sahip olmamasından kaynaklandığı açıktır. % 50 boş belleğe sahip olmak, bu özel başarısızlıkla ilgili değildir.
Andrzej Doyle

1
Yeni iş parçacığı oluşturmak için gerekli diğer kaynaklar nelerdir. RAM'i arttırırsak daha fazla iş parçacığı oluşturabileceğimizi düşünüyorduk. Lütfen bize rehberlik edin
Deepak Tewani

Yanıtlar:


80

Bu, istisna adı şiddetle önerilmesine rağmen bir bellek sorunu değil, bir işletim sistemi kaynak sorunudur. Yerel iş parçacıklarınız, yani işletim sisteminin JVM'nizin kullanmasına izin vereceği iş parçacığı bitiyor.

Bu nadir bir sorundur çünkü nadiren bu kadar çok kişiye ihtiyacınız vardır. İpliklerin olması gereken, ancak bitmeyen çok sayıda koşulsuz iplik yumurtlamanız var mı?

Mümkünse, bir Yürütücünün kontrolü altında Çağrılabilir / Çalıştırılabilirleri kullanmaya yeniden yazmayı düşünebilirsiniz. Kodunuzun kolayca kontrol edebileceği çeşitli davranışlara sahip çok sayıda standart yürütücü vardır.

(İş parçacığı sayısının sınırlı olmasının birçok nedeni vardır, ancak bunlar işletim sisteminden işletim sistemine farklılık gösterir)


Cevap için teşekkürler. Açık kaynak kodlu bir kütüphane ICE4j kullanıyoruz ve bunu test etmeye çalışıyoruz. Sunucuda% 50 bellek kaldığını bildiğimizde işletim sistemindeki iş parçacığı sınırını artıramayız.
Deepak Tewani

Muhtemelen, ama bence sana bu şekilde yardımcı olmayacak. Yük testi sırasında kaynaklarınız tükenirse, uygulamanızda ne olacağını kontrol edebilmeniz gerekir. Neden aynı anda 32000 aktif iş parçacığınız var?
Thorbjørn Ravn Andersen

UDP soketlerine veri yazmak ve okumak için 32 K iş parçacığı kullanan 11K istemciler oluşturuyoruz. Bu 32 K iş parçacığından 10K iş parçacığı, soketi açık tutmak için kullanılan iplikleri canlı tutuyor
Deepak Tewani

Bu sorunun modern web sunucularında çözüldüğüne inanıyorum. Ayrıca udp paketleri gevşetebilir - herhangi bir nedenle sadece bir web sunucusu kullanmıyorsunuz?
Thorbjørn Ravn Andersen

7
Çünkü OutOfMemory istisnası OutOfResources olarak adlandırılmış olmalıdır. İşletim sistemi ihtiyacınız olan kaynağı sağlayamaz. (Ve ice4j'i bilmediğim ortaya çıktı)
Thorbjørn Ravn Andersen

14

Yük testi sırasında aynı sorunla karşılaştım, bunun nedeni JVM'nin yeni bir Java iş parçacığı oluşturamamasıdır. JVM kaynak kodu aşağıdadır

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);`

Temel neden: JVM, JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR (kaynaklar tükendiğinde (bellek tükendiğinde) veya JVMTI_RESOURCE_EXHAUSTED_THREADS (İş parçacığı bittiğinde) bu istisnayı atar.

Benim durumumda Jboss, isteği yerine getirmek için çok fazla iş parçacığı oluşturuyor, ancak tüm iş parçacıkları engellendi. Bu nedenle, JVM bellek ile birlikte iş parçacıklarıyla da tükenmiştir (her iş parçacığı, her iş parçacığı engellendiği için serbest bırakılmayan belleği tutar).

İncelenen java iş parçacığı dökümlerinin yaklaşık 61 bin iş parçacığının yöntemimizden biri tarafından engellendiğini ve bu soruna neden olduğunu gözlemledik. Konu dökümü bölümü aşağıdadır

"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)

Yöntem nasıl engelleniyordu? Asla geri dönmeyecek misin?
Thorbjørn Ravn Andersen

8

İşletim sisteminizin oluşturmaya çalıştığınız iş parçacığı sayısına izin vermemesi veya JVM'de bir sınıra ulaşmanız muhtemeldir. Özellikle 32k gibi yuvarlak bir sayı ise, şu veya bu türden bir limit çok büyük olasılıkla suçludur.

Gerçekten 32k iş parçacığına ihtiyacınız olduğundan emin misiniz? Çoğu modern dil, yeniden kullanılabilir iş parçacığı havuzları için bir tür desteğe sahiptir - eminim Java'da da bir şeyler vardır ( ExecutorServiceJesper kullanıcısının bahsettiği gibi). El ile yenilerini oluşturmak yerine, böyle bir havuzdan iş parçacığı isteyebilirsiniz.


1
Cevabınız için teşekkürler Açık kaynak kodlu bir kütüphane ICE4j kullanıyoruz ve bunu test etmeye çalışıyoruz. Sunucuda% 50 bellek kaldığını bildiğimizde işletim sistemindeki iş parçacığı sınırını artıramayız.
Deepak Tewani

1
UDP soketlerine veri yazmak, okumak için 32 K iş parçacığı kullanan 11K istemciler oluşturuyoruz. Bu 32 K iş parçacığından, 10K iş parçacığı, soketi açık tutmak için kullanılan iplikleri canlı tutuyor
Deepak Tewani

7

İplik Yığın Boyutuna da bakmanızı ve daha fazla iş parçacığı oluşturup oluşturmadığınızı görmenizi tavsiye ederim. JRockit 1.5 / 1.6 için varsayılan İplik Yığın Boyutu , Linux OS üzerinde 64 bit VM için 1 MB'dir. 32K iş parçacığı, bu gereksinimi karşılamak için önemli miktarda fiziksel ve sanal bellek gerektirir.

Başlangıç ​​noktası olarak Yığın Boyutunu 512 KB'ye düşürmeyi deneyin ve uygulamanız için daha fazla iş parçacığı oluşturmaya yardımcı olup olmadığına bakın. Ayrıca yatay ölçeklendirmeyi keşfetmenizi de tavsiye ederim, örneğin uygulama işlemlerinizi daha fazla fiziksel veya sanal makineye bölmek.

64 bit VM kullanırken, gerçek sınır işletim sisteminin fiziksel ve sanal bellek kullanılabilirliğine ve ulimitc gibi işletim sistemi ayarlama parametrelerine bağlı olacaktır. Aşağıdaki makaleyi de referans olarak tavsiye ederim:

OutOfMemoryError: yeni yerel iş parçacığı yaratılamıyor - Sorun Çözüldü


5

Jvm, systemd aracılığıyla başlatılırsa, bazı Linux işletim sistemlerinde işlem başına maxTasks sınırı (görevler aslında evreler anlamına gelir) olabilir.

Bunu "servis durumu" çalıştırarak kontrol edebilir ve bir maxTasks limiti olup olmadığını kontrol edebilirsiniz. Varsa, /etc/systemd/system.conf dosyasını düzenleyerek, bir yapılandırma ekleyerek kaldırabilirsiniz: DefaultTasksMax = infinity


3

Bash'de top kullanırken görünmeyen hayalet süreçler nedeniyle aynı sorunu yaşadım. Bu, JVM'nin daha fazla iş parçacığı oluşturmasını engelledi.

Benim için, tüm java işlemlerini jps ile listelerken çözüldü (sadece jpskabuğunuzda çalıştırın ) ve bunları kullanarak ayrı ayrı öldürdü.kill -9 pid her hayalet işlemi için bash komutunu .

Bu, bazı senaryolarda yardımcı olabilir.


2

java.lang.OutOfMemoryError: Unable to create new native threadJVM işletim sisteminden yeni bir iş parçacığı istediğinde bununla yüzleşme şansınız var . Temel işletim sistemi yeni bir yerel iş parçacığı ayıramadığında, bu OutOfMemoryError atılır. Yerel iş parçacıkları için kesin sınır çok platforma bağlıdır, bu nedenle aşağıdaki bağlantı örneğine benzer bir test çalıştırarak bu sınırları bulmanızı tavsiye eder. Ancak, genel olarak, neden olan durum java.lang.OutOfMemoryError: Unable to create new native threadaşağıdaki aşamalardan geçer:

  1. JVM içinde çalışan bir uygulama tarafından yeni bir Java iş parçacığı isteniyor
  2. JVM yerel kodu, işletim sistemine yeni bir yerel iş parçacığı oluşturma isteğini temsil eder İşletim sistemi, iş parçacığına bellek ayrılmasını gerektiren yeni bir yerel iş parçacığı oluşturmaya çalışır.
  3. İşletim sistemi, 32 bitlik Java işlem boyutu bellek adres alanını tükettiğinden - örneğin (2-4) GB işlem boyutu sınırına ulaşıldığı için - ya da işletim sisteminin sanal belleği tamamen tükendiği için yerel bellek tahsisini reddedecektir.
  4. Java.lang.OutOfMemoryError: Yeni yerel iş parçacığı oluşturulamıyor hatası atılır.

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


2

Hangi işlemlerin iş parçacığı oluşturduğunu bulmak için şunu deneyin:

ps huH

Normalde çıktıyı bir dosyaya yönlendiririm ve dosyayı çevrimdışı olarak analiz ederim (her işlem için iş parçacığı sayısının beklendiği gibi olup olmadığıdır)


1

İşiniz, düğümlerdeki OutOfMemmory nedeniyle başarısız oluyorsa, maksimum harita ve indirgeyici sayınızı ve her biri için JVM seçeneklerini tweekleyebilirsiniz. mapred.child.java.opts (varsayılan değer 200Xmx'tir) genellikle veri düğümlerinize özgü donanıma göre artırılmalıdır.

Bu bağlantı yardımcı olabilir ... lütfen kontrol edin


1
Hepimiz bu bağlantıda verilen değişikliği zaten denedik. Ancak sonuç aynı :(
Deepak Tewani

1

JBoss yapılandırmanızda bazı sorunlar var, /opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m Xms ve Xmx, JBoss bellek kullanımınızı yapılandırılmış değere sınırlıyor, bu nedenle sunucunuz 8 Gb'den yalnızca 512M kullanıyor + kendi amacı için biraz fazladan, bu sayıyı artırın, işletim sistemi ve orada çalışan diğer şeyler için biraz boş bırakmayı unutmayın ve belki de tatsız kodlara rağmen çalıştırıyor olabilirsiniz. Mümkünse kodu düzeltmek de güzel olurdu.


1

Bu hata aşağıdaki iki nedenden dolayı ortaya çıkabilir:

  • Bellekte yeni iş parçacıkları barındıracak yer yok.

  • İş parçacığı sayısı İşletim Sistemi sınırını aşıyor.

İş parçacığı sayısının java işlemi için sınırı aştığından şüpheliyim

Muhtemelen sorun hafıza yüzünden olabilir. Dikkate alınması gereken bir nokta şudur:

iş parçacıkları JVM yığını içinde oluşturulmaz. JVM yığınının dışında oluşturulurlar. Dolayısıyla, RAM'de daha az yer kaldıysa, JVM yığın ayırmasından sonra, uygulama “java.lang.OutOfMemoryError: yeni yerel iş parçacığı yaratılamıyor” ile çalışacaktır.

Olası Çözüm, yığın belleğini azaltmak veya genel ram boyutunu artırmaktır


0

Aynı sorunu yaşadım ve bir java API'sinin uygunsuz kullanımı olduğu ortaya çıktı. Birden fazla kez başlatılması gerekmeyen bir toplu işleme yönteminde bir oluşturucuyu başlatıyordum.

Temelde şöyle bir şey yapıyordum:

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

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

bunu ne zaman yapmalıydım:

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

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

-4

Her şeyden önce işletim sistemini / sanal makinesini bu kadar suçlamazdım .. daha çok çok sayıda İş parçacığı oluşturan kodu yazan geliştiriciyi . Temelde kodunuzun bir yerinde (veya 3. taraf) çok sayıda iş parçacığı kontrolsüz oluşturulur .

Yığın izlerini / kodu dikkatlice inceleyin ve oluşturulan iş parçacığı sayısını kontrol edin. Normalde uygulamanız farklı bir sorunsa, büyük miktarda iş parçacığına ihtiyaç duymamalıdır.


10
Bu sorunun çözümü değil.
ftrujillo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.