2012-05-24 8 views
11

Ich habe gelesen und getestet und schlug meinen Kopf an der Wand für mehr als einen Tag wegen dieses Fehlers.Java "OutOfMemoryError" beim Erstellen von <100 Threads

Ich habe einige Java-Code in einer Klasse namens Listener die

ExecutorService executor = Executors.newFixedThreadPool(NTHREADS); 
boolean listening = true; 
int count = 0; 
while (listening) { 
    Runnable worker; 
    try { 
     worker = new ServerThread(serverSocket.accept()); // this is line 254 
     executor.execute(worker); 
     count++; 
     logger.info("{} threads started", count); 
    } catch (Exception e1){ 
     //... 
    } 
} 

ich die JVM-Einstellungen -Xmx Tweaking wurden (überall von 1 bis 15 g) (von 104k bis 512M überall) und -Xss wie diese aussieht. Der Server verfügt über 24 GB RAM, muss aber auch die Datenbank ausführen, die das Programm unterstützt.

Nach 2-20 Fäden erstellt werden (ein paar Dutzend existieren an anderer Stelle im Programm als auch), erhalte ich die Fehler

Exception in thread "Thread-0" java.lang.OutOfMemoryError: unable to create new native thread 
at java.lang.Thread.start0(Native Method) 
at java.lang.Thread.start(Thread.java:657) 
at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:943) 
at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1325) 
at xxx.Listener.run(Listener.java:254) 

$java -version ergibt:

java version "1.6.0_24" 
OpenJDK Runtime Environment (IcedTea6 1.11.1) (fedora-65.1.11.1.fc16-x86_64) 
OpenJDK 64-Bit Server VM (build 20.0-b12, mixed mode) 

Es ist immer eine große In diesem Fall ist der freie Speicher auf dem System frei und andere Programme werden weiterhin ordnungsgemäß ausgeführt. Was verursacht Java, dass es keinen Speicher mehr für neue Threads hat?

UPDATE: Vielleicht ist größer, als ich dachte- ich es geschafft, diesen Fehler zu bekommen (nur einmal), wenn ich ^C verwendet:

OpenJDK 64-Bit Server VM warning: Exception java.lang.OutOfMemoryError occurred dispatching signal SIGINT to handler- the VM may need to be forcibly terminated 

und das gleiche passiert, wenn ich versuchte, das zu töten Client (auch in Java und läuft auf dem gleichen Server geschrieben, ist es ein einzelner Thread, der eine Datei liest und sendet sie an den Server über die Socket), so gibt es auf jeden Fall eine Grenze, jenseits der JVM eine mit dem anderen zu stören verursacht, aber ich kann mir nicht vorstellen, was passiert, wenn ich noch freie Speicher habe und keinen Swap benutze? Server -Xmx1G -Xss104k Client--Xmx10M

UPDATE2: Aufgeben der Perl-Bibliothek Forks::Super und laufen die Kunden von bash lassen Sie mich zu 34 Threads aufstehen, bevor der Server mit OOME abgestürzt, so dass mehrere Clients laufen auf jeden Fall einen Einfluss hatte auf dem Server, aber zur gleichen Zeit soll ich noch in der Lage sein, mehr als 34 laufen Java-Threads zu einem Zeitpunkt (68, wenn einer der Clients zählt). Welche Systemressourcen blockieren die Erstellung von mehr Threads (d. H. Wo soll ich suchen, um das Schwein zu finden)? Wenn alles (Clients, Server, GC ...) läuft zur gleichen Zeit der Erinnerung heraus, sagt top dies über meine CPU- und Speichernutzung:

Cpu(s): 0.0%us, 0.0%sy, 0.0%ni,100.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st 
Mem: 24681040k total, 1029420k used, 23651620k free, 30648k buffers 
Swap: 26836988k total,  0k used, 26836988k free, 453620k cached 

UPDATE3: Ist das hs_error log unten zeigen, dass meine Java ist nicht 64 Bit?

# There is insufficient memory for the Java Runtime Environment to continue. 
# Cannot create GC thread. Out of system resources. 
# Possible reasons: 
# The system is out of physical RAM or swap space 
# In 32 bit mode, the process size limit was hit 
# Possible solutions: 
# Reduce memory load on the system 
# Increase physical memory or swap space 
# Check if swap backing store is full 
# Use 64 bit Java on a 64 bit OS 
# Decrease Java heap size (-Xmx/-Xms) 
# Decrease number of Java threads 
# Decrease Java thread stack sizes (-Xss) 
# Set larger code cache with -XX:ReservedCodeCacheSize= 
# This output file may be truncated or incomplete. 
# 
# JRE version: 6.0_24-b24 
# Java VM: OpenJDK 64-Bit Server VM (20.0-b12 mixed mode linux-amd64 compressed oops) 
# Derivative: IcedTea6 1.11.1 
# Distribution: Fedora release 16 (Verne), package fedora-65.1.11.1.fc16-x86_64 
+0

Ist die ServerThread-Instanz von java.lang.Thread? Dann sollte es mit Thread.start() gestartet werden, und Thread-Pool ist nicht sinnvoll. Wenn nicht, wie werden Sie Socket-Verbindung mit einem einfachen Runnable dienen? Es ist knifflig, da Tasks, die von einem Threadpool gesteuert werden, nicht auf Eingaben warten können oder Threads (Deadlock) auftreten können. –

+0

ServerThread ist eine schlecht benannte Klasse von mir selbst 'öffentliche Klasse ServerThread implementiert Runnable {... public void run() {...} ...}' Ich sehe Ihre Sorge, dass es möglicherweise schlecht warten würde Eingabe in einen Pool (es gibt eine Timeout-Funktion), aber ich möchte nicht jedes Mal, wenn ein Client eine Verbindung herstellt, einen neuen Thread erstellen - das wäre ein enormer Overhead für relativ kurze Interaktionen und würde trotzdem meine Thread-Erstellungsprobleme nicht lösen. – kaz

+0

Haben Sie getestet, wie viele Threads Sie in einer einfacheren Anwendung erstellen können? – Jivings

Antwort

11

können Sie sein Limit von max user processes, zu wissen, dass Ihr Limit Einsatz:

ulimit -u 

Um die Grenze zu ändern:

In /etc/security/limits.conf Satz:

user soft nproc [your_val] 
user hard nproc [your_val] 

Sie müssen einige eintragen Andere Konfiguration, wenn es nicht genug ist, siehe link.

Hinweis: Das OP fand diese bug report in Fedora und Centos, die die Einschränkungen der Bearbeitung /etc/security/limits.conf erläutert.

+0

Ich wäre dämmte, wenn das ist Ursache meiner Kopfschmerzen mit Version von Centos 6 ich benutze. Wildcard (*) in Wild bestraft. Nicht nur ich, sondern Pro-Support-Leute wussten das anscheinend nicht – nir

3

Ihr Problem hängt wahrscheinlich damit zusammen, dass JVM nicht in der Lage ist, Stapelspeicher für neue Threads zuzuweisen. Ironischerweise kann dieses Problem gelöst werden, indem der Heap-Speicherplatz (-Xmx) und der Stack-Speicherplatz (-Xss) verringert werden. Hier finden Sie zum Beispiel eine gute Erklärung: http://www.blogsoncloud.com/jsp/techSols/java-lang-OutOfMemoryError-unable-to-create-new-native-thread.jsp

+0

Ich wünschte, es wäre so einfach, aber irgendwie mit '-Xmx1G -Xss104k'I konnte 6 Threads erstellen (für insgesamt weniger als 40 explizit in meinem Programm erstellt).104k ist der Mindestwert -Xss auf meinem System, und 1G ist bei weitem nicht so groß, wie es in der Produktion sein muss. Inzwischen gibt es noch eine riesige Menge (über 8G) frei auf dem System, wenn es nicht genügend Speicher hat. – kaz

+0

104k ist ein seltsamer Wert :) dieses doc sagen über 64k Minimum http://www.oracle.com/technetwork/java/hotspotfaq-138619.html#threads_oom –

+0

Seltsam, aber wenn ich die JVM mit weniger als 104 starten wirft diese Nachricht und stürzt ab: 'Die angegebene Stackgröße ist zu klein. Geben Sie mindestens 104k an Die Java Virtual Machine konnte nicht erstellt werden.' – kaz

3

Es fehlt nicht Speicher für Ihre neuen Threads, es fehlen tatsächliche Threads. Das System stoppt Sie wahrscheinlich: Die Anzahl der Threads, die ein Benutzer erstellen kann, ist begrenzt.Sie können es auf diese Weise abfragen:

cat /proc/sys/kernel/threads-max 

Beachten Sie, dass Sie von anderen Prozessen auf der gleichen Maschine betroffen sein könnten, Sie sie zu viele Thread erstellen. Sie könnten diese Frage nützlich finden: Maximum number of threads per process in Linux?

+0

'$ cat/proc/sys/kernel/threads-max' gibt 385345- auf einem Server zurück Mit meinem Programm, einigen ssh/bash-Shells und MySQL glaube ich nicht, dass ich dieses Limit erreiche. Auch einige besonders schreckliche jvm-Einstellungen führen dazu, dass es abstürzt, nachdem weniger Threads erstellt wurden als andere, was darauf hindeutet, dass es sich um ein JVM-Problem handelt. – kaz

1

Nur zur Klarstellung:

Sie bieten eine ServerSocket zum Thread. Senden Sie Daten an diesen Socket? Vielleicht speichern Sie zu viele Daten im Thread-Kontext. Suchen Sie nach einem Muster, in dem Sie Streamdata in einem byte[] speichern.

+0

Nein, ich stelle dem Thread einen 'Socket' zur Verfügung,' ServerSocket.accept() 'gibt ein' Socket'-Objekt zurück. Und ja, ich übermittle Daten von einem anderen Programm und lese diese Daten, verarbeite sie und trenne dann die Verbindung. In der Testversion akzeptiert der Thread nur den Socket, wartet, schließt ihn dann und stirbt. Der Socket wird wie ein Stream gelesen, daher glaube ich nicht, dass ich den gesamten Inhalt dieses Streams an den Thread weitergebe. Darüber hinaus, bis der Client authentifiziert, sendet es keine Daten an den Stream-Puffer wird nur ein paar hundert Bytes sein. – kaz