web-dev-qa-db-ja.com

javaでのプログラムのデッドロック検出

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

55
Raji

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が内部で使用しているものです。

61
Adamski

調査のための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)
    ...
12
Nicolas Simonet

ThreadMXBeanクラスを使用して、プログラムでデッドロックスレッドを検出できます。次のコードは、

    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");
    }

デッドロックスレッドを検出する方法の詳細については、 here をクリックしてください。

4
user2485429

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

JArmusを使用するには、コードをインスツルメントする必要があります。インスツルメントされたクラスの1つを使用するか、JArmusインストゥルメントjarmuscを使用して自動的に。

_Java -jar jarmusc.jar yourprogram.jar checkedprogram.jar_

入力_yourprogram.jar_は、チェックするプログラムです。出力は、デッドロックを自動的に検出するためのチェック付きの同じプログラムです。

障壁には助けが必要

クラスCyclicBarrierCountDownLatchPhaserを使用したデッドロックの検証は少し注意が必要です。たとえば、JConsoleはこれらのタイプのデッドロックを検出できません。 JArmusには少し助けが必要です。同期に影響を与えるスレッドを指定する必要があります。これらのスレッドをregisteredスレッドと呼びます。

できるだけ早く、スレッドは自分自身を登録済みとしてマークする必要があります。登録済みのスレッドをマークする適切な場所は、開始メソッド_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();
_
3

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

2
RichardOD

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

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

2
oxbow_lakes

tempus-fugit は、プログラムスレッドダンプクラスとともに実装します。上記のmbeanメカニズムを使用して実装されており、すぐに使用できるスーパードゥーパーソリューションを提供します。

1
Toby

ここにコードがあります: http://www.Java2s.com/Code/Java/Development-Class/Performingdeadlockdetectionprogrammatically with application using the 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;
  }
_

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

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

1
Aaron Digulla

実行時に実行したい場合は、 watchdog を使用できます。

0
Artem Barger