(Используете ли статические инициализаторы в Java является хорошей идеей, выходит за рамки данного вопроса.)Как диагностировать или обнаружить тупики в Java статические инициализаторы
Я встречая тупики в моем приложении Scala, которые я считаю вызванных блокировкой статических инициализаторов в скомпилированных классах.
Мой вопрос заключается в том, как обнаружить и диагностировать эти взаимоблокировки. Я обнаружил, что обычные инструменты JVM для взаимоблокировок не работают, когда задействуются блоки статического инициализатора.
Вот простой пример Java приложение, которое ТУПИКИ в статическом инициализаторе:
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();
}
}
Если запустить это приложение, оно ТУПИКИ. Трассировки стеки во время тупика (из jstack
) содержат следующие два зашедших в тупике темы:
"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 <0x000000004a6a7870> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1143)
- locked <0x000000004a6a7870> (a java.lang.Thread)
at java.lang.Thread.join(Thread.java:1196)
at StaticDeadlockExample.<clinit>(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
Моими вопросов является
- Почему первый поток помечен как Runnable, когда это на самом деле ожидая на замке? Могу ли я каким-то образом определить «реальное» состояние этого потока?
- Почему ни один поток не помечен как имеющий какие-либо (соответствующие) блокировки, когда на самом деле один удерживает статический блокиратор intializer, а другой ждет его? Могу ли я каким-то образом обнаружить блокировку статического инициализатора?
Почему, на ваш взгляд, это ожидание на замке? Если он ожидал блокировки, он (1) находился бы в состоянии WAITING, а не RUNNABLE и (2), упомянул бы «« Ожидание на ... »или« Ожидание блокировки »после верхней записи стека. – Dima
Я не думаю [эти блокировки инициализации] (http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html # jls-12.4.2). Они управляются JVM для этого процесса. Возможно, свалки потоков не раскрывают их. –
@ Dima - Я знаю, что он ждет блокировки, потому что я построил код так, чтобы он был. Вышеупомянутая программа будет зависеть навсегда, если вы ее запустите - попробуйте сами. Вы считаете, что он не использует 'java.util.concurrent.locks'? Если так - это правильно, но не очень полезно. –
Rich