Javaでプログラムによるデッドロック検出
-
12-09-2019 - |
質問
私はをすることができますどのようにプログラムでのデッドロックは、Javaプログラムで発生したことを検知する?
正しい解決策はありません
他のヒント
あなたはこのプログラムでそのJDKに付属ThreadMXBean
を使用して行うことができます
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.
}
}
もちろん、あなたがこのデッドロックのチェックを実行している方のスレッドに分離してみてください! - そのスレッドは、チェックを実行することができませんデッドロックそれ以外の場合は、
ちなみにこれはJConsoleのは、カバーの下に使用されているものです。
調査するための1つの有用なヒント:
あなたは赤利きアプリケーションをキャッチし、デッドロックが発生した疑いがある、行くとのjava.exeコンソールウィンドウで押して「Ctrlキーを押しながらブレーク」(またはSolaris / Linux上の「はCtrl- \」)ことができます。 JVMは、すべてのスレッドの現在の状態とスタックトレースをダンプ死んでロックを見つけると、正確にそれらを記述します。
これは、次のようになります
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)
...
あなたは、プログラムThreadMXBean class.Hereがコードで使用してデッドロックスレッドを検出することができ、
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");
}
を検出する方法についての詳細はこちらこちらをクリックしますデッドロックのスレッドます。
JArmus のデッドロック検出および回避するためのライブラリです。それはのためのサポートが含まれています。
Thread.join
、CyclicBarrier
、CountDownLatch
、Phaser
、および
ReentrantLock
ます。
あなたが楽器にあなたのコードを必要とするJArmusを使用します。どちらのJArmusのinstrumentarのjarmusc
とそのインストルメントクラスのいずれかに自動的に通じます。
java -jar jarmusc.jar yourprogram.jar checkedprogram.jar
入力yourprogram.jar
は、あなたがチェックしたいプログラムです。
出力は自動的にデッドロックを見つけるためのチェックと同じプログラムです。
障壁はいくつかの助けが必要
クラスCyclicBarrier
、CountDownLatch
、Phaser
とデッドロックの確認例えば、JConsoleはデッドロックのこれらのタイプを検出することができない---ビットトリッキーです。 JArmusはあなたからの少しの助けを必要とする:あなたはスレッドが同期に影響を与えているかを指定する必要があり、我々はの登録のスレッドこれらを呼び出します。
できるだけ早く、スレッドが自身をマークする必要があります。登録されたスレッドをマークするのに適した場所は、最初の方法Runnable.run
です。
JArmus.register(latch);
例
デッドロック次のプログラムが正しくによって識別されます 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();
あなたは IBMのMTRAT を検討する必要があります。予防は、すべての後の治療よりも優れています。また、デッドロック検出ツールが付属していますのマルチコア・ソフトウェア開発キットます。
は、をJConsoleのを介して、これを行うことができます。スレッドタブの「デッドロックを検出する」ボタンがあります。 JDK6では、これは、固有モニタとj.u.c
のLock
s両方に対するロックを検出する
$JAVA_HOM/bin/jconsole
コマンドでJConsoleをアップ実行します。
魔法が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;
}
これは、Java 5と6で別の名前(したがって、外側ThreadMXBean
)を有するif()
のAPIを呼び出します。
のコード例もロックを中断することができますので、あなたも、デッドロックを解除することができます。
テンパス-fugit にもクラスをダンププログラムスレッドと一緒にそれを実装します。これは、前述したMBeanのメカニズムを使用して実装し、すぐにスーパー大型のソリューションの低下を提供していますいます。
あなたはそれがあなたのためにウォッチドッグを使用することができ、実行時に行われるようにしたい場合そのます。