Search code examples
javamultithreadingdeadlockjconsole

Analyzing deadlock using Jconsole


I am running a simple program which causes deadlock.

    final  String resource1 = "santanu";
    final String resource2 = "sahoo";
     System.out.println(Integer.toHexString(resource1.hashCode())    );
     System.out.println(Integer.toHexString(resource2.hashCode()) );

    Thread t1 = new Thread(){

        public void run()
        {
            synchronized (resource1) {
                System.out.println("Thread 1: locked resource 1");  
                try {

                    Thread.sleep(200);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (resource2) {
                     System.out.println("Thread 1: locked resource 2");     
                }               
            }
        }
    };
    Thread t2 = new Thread(){
        public void run()
        {
            synchronized (resource2) {
                try {
                     System.out.println("Thread 2: locked resource 2");  
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                                            e.printStackTrace();
                }
                synchronized (resource1) {
                     System.out.println("Thread 2: locked resource 1");  
                }
            }
        }
    };

    t1.start();
    t2.start();

Below is the expected output

6f3700d4      
6823b3a        
Thread 1: locked resource 1
Thread 2: locked resource 2

Now I fired jps command and found the PID for this java program and using jconsole <pid> command to view the deadlock.

Below is the stack trace in jconsole

Name: Thread-1
State: BLOCKED on java.lang.String@4ad61aef owned by: Thread-0
Total blocked: 1  Total waited: 1

Stack trace: 
 com.cmc.santanusol$2.run(santanusol.java:49)
   - locked java.lang.String@4406cef4

Now my question is why jconsole stacktrace displaying different object's HexString ( java.lang.String@ )comparing to the values i am printing in first two sysout ?

More precisely why 6f3700d4 and 6823b3a values did not appear in jconsole output ?


Solution

  • The problem is that String overrides hashCode. Use

    System.out.println(Integer.toHexString(System.identityHashCode(resource1)));
    System.out.println(Integer.toHexString(System.identityHashCode(resource2)));
    

    for debugging.

    Background: Object returns

    getClass().getName() + "@" + Integer.toHexString(hashCode());
    

    in toString, but String and other classes override toString (with strings that would not be helpful in this context), therefore JConsole shows the info as it would have been shown by the original Object.toString.