title: How to diagnose or detect deadlocks in Java static initializers
body: <p>(Whether using static initializers in Java is a good idea is out of scope for this question.)</p>
  
  <p>I am encountering deadlocks in my Scala application, which I think are caused by interlocking static initializers in the compiled classes.</p>
  
  <p>My question is how to detect and diagnose these deadlocks -- I have found that the normal JVM tools for deadlocks do not seem to work when static initializer blocks are involved.</p>
  
  <p>Here is a simple example Java app which deadlocks in a static initializer:</p>
  
  <pre><code>public class StaticDeadlockExample implements Runnable
  {
      static
      {
          Thread thread = new Thread(
                  new StaticDeadlockExample(),
                  "StaticDeadlockExample child thread");
          thread.start();
          try {
              thread.join();
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
      }
  
      public static void main(String[] args)
      {
          System.out.println("in main");
      }
  
      public static void sayHello()
      {
          System.out.println("hello from thread " + Thread.currentThread().getName());
      }
  
      @Override
      public void run() {
          StaticDeadlockExample.sayHello();
      }
  }
  </code></pre>
  
  <p>If you launch this app, it deadlocks. The stack trace at time of deadlock (from <code>jstack</code>) contains the following two deadlocked threads:</p>
  
  <pre><code>"StaticDeadlockExample child thread" prio=6 tid=0x000000006c86a000 nid=0x4f54 in Object.wait() [0x000000006d38f000]
     java.lang.Thread.State: RUNNABLE
      at StaticDeadlockExample.run(StaticDeadlockExample.java:37)
      at java.lang.Thread.run(Thread.java:619)
  
     Locked ownable synchronizers:
      - None
  
  "main" prio=6 tid=0x00000000005db000 nid=0x2fbc in Object.wait() [0x000000000254e000]
     java.lang.Thread.State: WAITING (on object monitor)
      at java.lang.Object.wait(Native Method)
      - waiting on &lt;0x000000004a6a7870&gt; (a java.lang.Thread)
      at java.lang.Thread.join(Thread.java:1143)
      - locked &lt;0x000000004a6a7870&gt; (a java.lang.Thread)
      at java.lang.Thread.join(Thread.java:1196)
      at StaticDeadlockExample.&lt;clinit&gt;(StaticDeadlockExample.java:17)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:169)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:116)
  
     Locked ownable synchronizers:
      - None
  </code></pre>
  
  <p>My questions are as follows</p>
  
  <ol>
  <li>Why is the first thread marked as RUNNABLE, when it is in fact waiting on a lock? Can I detect the "real" state of this thread somehow?</li>
  <li>Why is neither thread marked as owning any (relevant) locks, when in fact one holds the static intializer lock and the other is waiting for it? Can I detect the static initializer lock ownership somehow?</li>
  </ol>