2012-10-11 16 views
5

Ich möchte einen Thread erstellen, der die Speicherauslastung und die CPU-Nutzung verfolgt.Generieren Sie einen Java-Thread-Dump, ohne neu zu starten.

Wenn die Anwendung eine hohe Ebene erreicht, möchte ich einen Heap-Dump oder einen Thread-Dump erstellen.

Gibt es eine Möglichkeit, eine Thread-Dump-Laufzeit ohne Neustart zu generieren?

+0

Thread.getAllStackTraces() wird Ihnen das meiste geben, was Sie wollen. Oder Sie können 'jstack {pid}' als externes Programm ausführen. –

+2

Ich kann mir keine Möglichkeit vorstellen, einen Thread-Dump zu erstellen, der einen Neustart erfordert ....;) –

+0

Thread.dumpStack() gibt Ihnen den Stack-Trace für den aktuellen Thread. –

Antwort

10

Hier ist, wie wir es programmatisch tun: http://pastebin.com/uS5jYpd4

Wir verwenden die JMXThreadMXBean und ThreadInfo Klassen:

ThreadMXBean mxBean = ManagementFactory.getThreadMXBean(); 
ThreadInfo[] threadInfos = mxBean.getThreadInfo(mxBean.getAllThreadIds(), 0); 
... 

Sie können auch eine kill -QUIT pid unter ~ Unix zu tun, die Stapel auf die Standard-out-Dump . Es gibt auch Jstack, um den Stapel einer JVM zu entladen.

Wir auch eine Automatisierung haben, die den Stapel Dumps, wenn die durchschnittliche Belastung der Anwendung über eine bestimmte Schwelle ist:

private long lastCpuTimeMillis; 
private long lastPollTimeMillis; 

public void checkLoadAverage() { 
    long now = System.currentTimeMillis(); 
    long currentCpuMillis = getTotalCpuTimeMillis(); 
    double loadAvg = calcLoadAveragePercentage(now, currentCpuMillis); 
    if (loadAvg > LOAD_AVERAGE_DUMP_THRESHOLD) { 
     try { 
      dumpStack("Load average percentage is " + loadAvg); 
     } catch (IOException e) { 
      // Oh well, we tried 
     } 
    } 
    lastCpuTimeMillis = currentCpuMillis; 
    lastPollTimeMillis = now; 
} 

private long getTotalCpuTimeMillis() { 
    long total = 0; 
    for (long id : threadMxBean.getAllThreadIds()) { 
     long cpuTime = threadMxBean.getThreadCpuTime(id); 
     if (cpuTime > 0) { 
      total += cpuTime; 
     } 
    } 
    // since is in nano-seconds 
    long currentCpuMillis = total/1000000; 
    return currentCpuMillis; 
} 

private double calcLoadAveragePercentage(long now, long currentCpuMillis) { 
    long timeDiff = now - lastPollTimeMillis; 
    if (timeDiff == 0) { 
     timeDiff = 1; 
    } 
    long cpuDiff = currentCpuMillis - lastCpuTimeMillis; 
    double loadAvg = (double) cpuDiff/(double) timeDiff; 
    return loadAvg; 
} 
+0

Vielen Dank für die Lösung !! –

0

Ja, Sie können Ihren eigenen Stack Dump mit den integrierten Management MXBeans generieren. Genauer gesagt, können Sie alle aktuellen ThreadInfos von der ThreadMXBean bekommen und den Inhalt an Ihren gewünschten Ort schreiben.

7

Um die Fäden der Norm aus Dump, Sie so etwas wie dieses

ThreadInfo[] threads = ManagementFactory.getThreadMXBean() 
     .dumpAllThreads(true, true); 
for(final ThreadInfo info : threads) 
    System.out.print(info); 

in Java 6 mit der ThreadMXBean Klasse tun kann. Aber ich würde vorschlagen, anstelle der Standardausgabe echtes Logging zu verwenden.

2

Versuchen „kill -quit“ PROCESS_ID zB

kill -QUIT 2134 

Diese wird den Thread-Dump auslösen, ohne ihn neu zu starten

+0

Auf jeden Fall das beste Merkmal. Und wenn Sie nur einen Java-Prozess haben, würde 'kill -QUIT' pidof java'' den Trick machen. – pdeschen

Verwandte Themen