65

Java プログラムでデッドロックが発生したことをプログラムで検出するにはどうすればよいですか?

4

9 に答える 9

68

ThreadMXBeanこれは、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.
    }
}

明らかに、このデッドロック チェックを実行しているスレッドを分離する必要があります。そうしないと、そのスレッドがデッドロックすると、チェックを実行できなくなります。

ちなみに、これは JConsole が内部で使用しているものです。

于 2009-07-09T07:49:40.740 に答える
14

調査に役立つ 1 つのヒント:

アプリケーションのレッドハンドをキャッチでき、デッドロックが発生した疑いがある場合は、java.exe コンソール ウィンドウで「Ctrl-Break」(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)
    ...
于 2009-07-09T07:43:34.040 に答える
3

JArmusは、デッドロックの検出と回避のためのライブラリです。Thread.joinCyclicBarrierCountDownLatchPhaser、および のサポートが含まれます ReentrantLock

JArmus を使用するには、コードを計測する必要があります。インストルメント化されたクラスの 1 つを介して、または JArmus インストルメンターを使用して自動的に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();
于 2014-05-05T15:06:35.300 に答える
2

IBM の MTRATを検討することをお勧めします。結局のところ、予防は治療よりも優れています。マルチコア ソフトウェア開発キットには、デッドロック検出ツールも付属しています。

于 2009-07-09T07:32:12.503 に答える
2

プログラムによる検出が必要ない場合は、JConsoleを介してこれを行うことができます。スレッドタブには、「デッドロックの検出」ボタンがあります。JDK6 では、これにより組み込みモニターとj.u.c Locks の両方のロックが検出されます。

$JAVA_HOM/bin/jconsoleコマンドを使用して JConsole を実行します。

于 2009-07-09T07:48:20.943 に答える
1

ここにコードがあります: http://www.java2s.com/Code/Java/Development-Class/JavalangmanagementAPI.htmを使用してアプリケーション内でプログラム的にデッドロック検出を実行する

魔法が起こる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;
  }

ThreadMXBeanこれは、 Java 5 と 6 で異なる名前を持つの API を呼び出します(したがって、 outer if())。

コード例ではロックを中断することもできるため、デッドロックを解消することもできます。

于 2011-11-16T10:15:39.033 に答える
1

tempus-fugitは、プログラムによるスレッド ダンプ クラスと共にそれを実装しています。上記の mbean メカニズムを使用して実装され、すぐに使用できるドロップインの超大型ソリューションを提供します。

于 2010-01-02T17:37:02.010 に答える
0

実行時に実行したい場合は、ウォッチドッグを使用できます。

于 2009-07-09T07:34:53.810 に答える