Nice programing

자바에서 프로그래밍 방식 교착 상태 감지

nicepro 2021. 1. 7. 21:21
반응형

자바에서 프로그래밍 방식 교착 상태 감지


Java 프로그램에서 교착 상태가 발생했음을 프로그래밍 방식으로 어떻게 감지 할 수 있습니까?


ThreadMXBeanJDK와 함께 제공되는를 사용하여 프로그래밍 방식으로이를 수행 할 수 있습니다 .

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이 커버 아래에서 사용하는 것입니다.


조사를위한 유용한 힌트 :

응용 프로그램이 빨간색으로 표시되고 교착 상태가 발생한 것으로 의심되면 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)
    ...

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

교착 상태 스레드를 감지하는 방법에 대한 자세한 정보를 보려면 여기클릭 하십시오 .


JArmus 는 교착 상태 감지 및 회피를위한 라이브러리입니다. 그것은에 대한 지원이 포함됩니다 : Thread.join, CyclicBarrier, CountDownLatch, Phaser,와 ReentrantLock.

JArmus를 사용하려면 코드를 계측해야합니다. 인스트루먼트 된 클래스 중 하나를 통해 또는 JArmus instrumentar를 사용하여 자동으로 jarmusc.

java -jar jarmusc.jar yourprogram.jar checkedprogram.jar

입력 yourprogram.jar은 확인하려는 프로그램입니다. 출력은 교착 상태를 자동으로 찾는 검사가있는 동일한 프로그램입니다.

장벽은 도움이 필요합니다

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

Example

The following program that deadlocks is correctly identified by 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();

You might want to consider IBM's MTRAT. Prevention is better than cure after all. The Multicore Software Development Kit also comes with a deadlock detection tool.


If you don't require programmatic detection you can do this via the JConsole; on the thread tab there is a "detect deadlock" button. In JDK6 this detect locks for both intrinsic monitors and j.u.c Locks

Run up the JConsole via the $JAVA_HOM/bin/jconsole command


There is code here: http://www.java2s.com/Code/Java/Development-Class/PerformingdeadlockdetectionprogrammaticallywithintheapplicationusingthejavalangmanagementAPI.htm

The magic happens 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;
  }

This calls an API of the ThreadMXBean which has a different name in Java 5 and 6 (hence the outer if()).

The code example also allows to interrupt the locks, so you can even break the deadlock.


tempus-fugit also implements it along with a programmatic thread dumping class. It's implemented using the mbean mechanism mentioned above and offers a drop in, out-of-the-box super duper solution.


In case you want it to be done in run-time you can use watchdog for that.

ReferenceURL : https://stackoverflow.com/questions/1102359/programmatic-deadlock-detection-in-java

반응형