How can I programmatically detect that a deadlock has occurred in a Java program?
JArmus is a library for deadlock detection and avoidance. It includes support for:
Thread.join, CyclicBarrier, CountDownLatch, Phaser, and
ReentrantLock.
To use JArmus you need to instrument your code. Either through one of its instrumented classes or automatically with the JArmus instrumentar jarmusc.
java -jar jarmusc.jar yourprogram.jar checkedprogram.jar
The input yourprogram.jar is the program you want to check.
The output is the same program with checks to automatically find any deadlock.
Verifying deadlocks with classes CyclicBarrier, CountDownLatch, Phaser is a bit tricky --- for example, JConsole cannot detect these types of deadlocks. JArmus needs a little help from you: you must specify which threads are influencing synchronization, we call these registered threads.
As soon as possible, the thread must mark itself as registered. A good place to mark registered threads is at the beginning method Runnable.run.
JArmus.register(latch);
The following program that deadlocks is correctly identified by JArmus:
final CountDownLatch latch = new CountDownLatch(2);
final CyclicBarrier barrier = new CyclicBarrier(2);
final Queue 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();