Detecting a deadlock with ThreadMBean in JDK 1.5

This example shows how to use the ThreadMBean class in JDK 1.5 to detect a deadlock. ThreadMBean is a management class (package java.lang.management) that provides functionality to query the thread system of the JVM.

The example creates three threads A, B and C which end up in a deadly embrace: A waits for a lock that B holds, B waits for a lock that C holds and C waits for a lock that A holds. The method findMonitorDeadlockedThreads returns the list of Thread ids involved in the deadlock.

FindDeadlock.java:

import java.lang.management.ManagementFactory;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMBean;
import java.lang.management.ThreadState;
 
public class FindDeadlock
{
   Object a = new Object();
   Object b = new Object();
   Object c = new Object();
   
   public static void main(String []args) {
      final FindDeadlock fd = new FindDeadlock();
   
      Thread t1 = new Thread() {
         public void run() {
            while (true) { fd.m1(); }
         }
      };
      
      Thread t2 = new Thread() {
         public void run() {
            while (true) { fd.m2(); }
         }
      };
      
      Thread t3 = new Thread() {
         public void run() {
            while (true) { fd.m3(); }
         }
      };      
      
      t1.setName("First thread");
      t2.setName("Second thread");
      t3.setName("Third thread");
      
      t1.start();
      t2.start();
      t3.start();
      
      // give the time for the threads to go into a deadlock
      try { Thread.sleep(1000); } catch(Exception e) { } 
      
      ThreadMBean mbean = ManagementFactory.getThreadMBean();
      long[] threads = mbean.findMonitorDeadlockedThreads();
      if (threads != null) {
         for (int i=0; i<threads.length; i++) { 
            ThreadInfo threadInfo = mbean.getThreadInfo(threads[i]);
            ThreadState threadState = mbean.getThreadState(threads[i]);
            
            System.out.print(threadInfo.getThreadName() + "(" + threadState + ") is waiting for ");
            System.out.print(threadInfo.getLockOwnerName() + " to release ");
            System.out.println("the lock " + threadInfo.getLockName());
         }
      }
   }
   
   public void m1() {
      synchronized(a) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(b) {
            System.out.println("m1 got through");
         }
      }
   }
   
   public void m2() {
      synchronized(b) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(c) {
            System.out.println("m2 got through");
         }
      }
   }
   
   public void m3() {
      synchronized(c) {
         try { Thread.sleep(100); } catch(Exception e) { }
         synchronized(a) {
            System.out.println("m3 got through");
         }
      }
   }   
}

outputs:

Third thread(Blocked) is waiting for First thread to release the lock java.lang.Object@d9f9c3
First thread(Blocked) is waiting for Second thread to release the lock java.lang.Object@1a46e30
Second thread(Blocked) is waiting for Third thread to release the lock java.lang.Object@3e25a5