Programmatische Systemverklemmungsdetektion in Java
-
12-09-2019 - |
Frage
Wie kann ich programmatisch erkennt, dass ein Deadlock in einem Java-Programm aufgetreten ist?
Keine korrekte Lösung
Andere Tipps
Sie können dies tun programmatisch die ThreadMXBean
, das mit dem JDK:
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long[] threadIds = bean.findDeadlockedThreads(); // Returns null if no threads are deadlocked.
if (threadIds != null) {
ThreadInfo[] infos = bean.getThreadInfo(threadIds);
for (ThreadInfo info : infos) {
StackTraceElement[] stack = info.getStackTrace();
// Log or store stack trace information.
}
}
Natürlich sollten Sie versuchen, zu isolieren, je nachdem, welchen Thread diese Deadlock-Prüfung durchführt - Andernfalls, wenn dieser Thread Deadlocks wird es nicht möglich sein, um die Prüfung laufen
Im übrigen ist es das, was JConsole ist unter der Decke verwendet wird.
Ein nützlicher Hinweis für die Untersuchung:
Wenn Sie die Anwendung fangen rot handed und vermuten, dass ein Deadlock aufgetreten ist, gehen und drücken Sie „Strg-Break“ in dem java.exe Konsolenfenster (oder „Strg- \“ auf Solaris / Linux). Die JVM wird den aktuellen Status und Stack-Trace aller Threads Dump, Riegelschlösser herausfinden und sie genau beschreiben.
Es wird wie folgt aussehen:
Full thread dump Java HotSpot(TM) Client VM (1.5.0_09-b03 mixed mode):
"[Test Timer] Request Queue" prio=6 tid=0x13d708d0 nid=0x1ec in Object.
wait() [0x1b00f000..0x1b00fb68]
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Unknown Source)
at library.util.AsyncQueue.run(AsyncQueue.java:138)
- locked <0x02e70000> (a test.server.scheduler.SchedulerRequestQueue)
...
Found one Java-level deadlock:
=============================
"Corba service":
waiting to lock monitor 0x13c06684 (object 0x04697d90, a java.lang.Object),
which is held by "[Server Connection] Heartbeat Timer"
"[Server Connection] Heartbeat Timer":
waiting to lock monitor 0x13c065c4 (object 0x0467e728, a test.proxy.ServerProxy), which is held by "Corba service"
Java stack information for the threads listed above:
===================================================
"Corba service":
at test.proxy.ServerProxy.stopHBWatchDog(ServerProxy:695)
- waiting to lock <0x04697d90> (a java.lang.Object)
...
Sie können die Deadlock-Threads erkennen programmatisch mit ThreadMXBean class.Here der Code ist,
ThreadMXBean bean = ManagementFactory.getThreadMXBean();
long ids[] = bean.findMonitorDeadlockedThreads();
if(ids != null)
{
ThreadInfo threadInfo[] = bean.getThreadInfo(ids);
for (ThreadInfo threadInfo1 : threadInfo)
{
System.out.println(threadInfo1.getThreadId()); //Prints the ID of deadlocked thread
System.out.println(threadInfo1.getThreadName()); //Prints the name of deadlocked thread
System.out.println(threadInfo1.getLockName()); //Prints the string representation of an object for which thread has entered into deadlock.
System.out.println(threadInfo1.getLockOwnerId()); //Prints the ID of thread which currently owns the object lock
System.out.println(threadInfo1.getLockOwnerName()); //Prints name of the thread which currently owns the object lock.
}
}
else
{
System.out.println("No Deadlocked Threads");
}
Klicken Sie auf hier für weitere Informationen darüber, wie zu erkennen die Deadlock-Threads.
JArmus ist eine Bibliothek zur Deadlock-Erkennung und Vermeidung. Es bietet Unterstützung für:
Thread.join
, CyclicBarrier
, CountDownLatch
, Phaser
und
ReentrantLock
.
Um JArmus verwenden Sie müssen Ihren Code Instrument. Entweder durch eine seiner instrumentierten Klassen oder automatisch mit dem JArmus instrumentar jarmusc
.
java -jar jarmusc.jar yourprogram.jar checkedprogram.jar
Der Eingang yourprogram.jar
ist das Programm, das Sie überprüfen möchten.
Der Ausgang ist das gleiche Programm mit überprüft automatisch alle Sackgassen zu finden.
Schranken brauchen Hilfe
Überprüfen Deadlocks mit Klassen CyclicBarrier
, CountDownLatch
, Phaser
ist ein bisschen schwierig --- zum Beispiel JConsole können diese Arten von Deadlocks nicht erkennen. JArmus braucht ein wenig Hilfe von Ihnen: Sie müssen angeben, welche Threads Synchronisation beeinflussen, nennen wir diese registriert Themen.
So bald wie möglich, muss der Faden selbst markiert als registriert. Ein guter Platz zum registrierten Gewinde Markierung wird am Anfang Methode Runnable.run
.
JArmus.register(latch);
Beispiel
Das folgende Programm, das korrekt identifiziert Deadlocks durch JArmus:
final CountDownLatch latch = new CountDownLatch(2);
final CyclicBarrier barrier = new CyclicBarrier(2);
final Queue<Exception> exceptions = new ArrayDeque<>();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
JArmus.register(barrier); // do not forget to register!
JArmus.register(latch); // do not forget to register!
latch.countDown();
latch.await();
barrier.await();
} catch (Exception e) {
exceptions.add(e);
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
JArmus.register(barrier); // do not forget to register!
JArmus.register(latch); // do not forget to register!
barrier.await();
latch.countDown();
latch.await();
} catch (Exception e) {
exceptions.add(e);
}
}
});
t1.start();
t2.start();
Sie können IBMs MTRAT zu betrachten. Vorbeugen ist besser als heilen, nachdem alle. Der Multicore- Software Development Kit auch mit einem Deadlock-Erkennung Werkzeug kommt.
Wenn Sie keine programmatische Erkennung benötigen Sie können dies tun, über die JConsole ; auf dem Gewinde Register gibt es einen „toten Punkt erfassen“ -Taste. In JDK6 erkennen diese Sperren für beide intrinsische Monitore und j.u.c
Lock
s
Führen Sie den JConsole über den $JAVA_HOM/bin/jconsole
Befehl up
Es gibt Code hier: http://www.java2s.com /Code/Java/Development-Class/PerformingdeadlockdetectionprogrammaticallywithintheapplicationusingthejavalangmanagementAPI.htm
Die Magie geschieht in ThreadMonitor.findDeadlock()
:
public boolean findDeadlock() {
long[] tids;
if (findDeadlocksMethodName.equals("findDeadlockedThreads")
&& tmbean.isSynchronizerUsageSupported()) {
tids = tmbean.findDeadlockedThreads();
if (tids == null) {
return false;
}
System.out.println("Deadlock found :-");
ThreadInfo[] infos = tmbean.getThreadInfo(tids, true, true);
for (ThreadInfo ti : infos) {
printThreadInfo(ti);
printLockInfo(ti.getLockedSynchronizers());
System.out.println();
}
} else {
tids = tmbean.findMonitorDeadlockedThreads();
if (tids == null) {
return false;
}
ThreadInfo[] infos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
for (ThreadInfo ti : infos) {
// print thread information
printThreadInfo(ti);
}
}
return true;
}
Dies erfordert eine API des ThreadMXBean
, die in Java 5 und 6 (daher der äußere if()
).
Das Codebeispiel ermöglicht auch die Sperren zu unterbrechen, so kann man sogar den Stillstand brechen.
tempus fugit- setzt sie auch zusammen mit einer programmatischen Faden Dumping Klasse. Es implementiert den mbean Mechanismus oben erwähnt, und bietet einen Tropfen in, out-of-the-box-Super-Duper-Lösung.
Falls Sie es möchten in der Laufzeit durchgeführt werden können Sie mit Watchdog das.