Raf*_*ffy 14 java static deadlock
这段代码会死锁:
public class Main {
static public final Object a = new Object();
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() { if (a == null); }
});
System.exit(0);
}
static public void main(final String[] args) {}
}
Run Code Online (Sandbox Code Playgroud)
此代码将正常退出:
public class Main {
static public final Object a = new Object();
static {
final Object aa = a;
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() { if (aa == null); }
});
System.exit(0);
}
static public void main(final String[] args) {}
}
Run Code Online (Sandbox Code Playgroud)
怎么了?
Tom*_*ine 14
重要的是在初始化时不同时访问类,因此保持锁定.
我想在第一种情况下发生的事情是:
Main.System.exit因为它不会返回.Main类以读取字段,但在类初始化时阻塞.因此陷入僵局.如果你写的话,它会更清楚if (a == null);一些if (Main.a == null);.
在第二种情况下,复制该值,因此关闭钩子不需要访问Main该类.
道德:不要混合线程和类初始化.Gafter和Bloch的Java Puzzlers书有更多内容.
这是死锁示例的字节码:
public class Main extends java.lang.Object{
public static final java.lang.Object a;
public Main();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
static {};
Code:
0: new #2; //class java/lang/Object
3: dup
4: invokespecial #1; //Method java/lang/Object."<init>":()V
7: putstatic #3; //Field a:Ljava/lang/Object;
10: invokestatic #4; //Method java/lang/Runtime.getRuntime:()Ljava/lang/Runtime;
13: new #5; //class Main$1
16: dup
17: invokespecial #6; //Method Main$1."<init>":()V
20: invokevirtual #7; //Method java/lang/Runtime.addShutdownHook:(Ljava/lang/Thread;)V
23: iconst_0
24: invokestatic #8; //Method java/lang/System.exit:(I)V
27: return
}
Run Code Online (Sandbox Code Playgroud)
这是正常完成的情况的字节码:
public class Main extends java.lang.Object{
public static final java.lang.Object a;
public Main();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: return
static {};
Code:
0: new #2; //class java/lang/Object
3: dup
4: invokespecial #1; //Method java/lang/Object."<init>":()V
7: putstatic #3; //Field a:Ljava/lang/Object;
10: getstatic #3; //Field a:Ljava/lang/Object;
13: astore_0
14: invokestatic #4; //Method java/lang/Runtime.getRuntime:()Ljava/lang/Runtime;
17: new #5; //class Main$1
20: dup
21: aload_0
22: invokespecial #6; //Method Main$1."<init>":(Ljava/lang/Object;)V
25: invokevirtual #7; //Method java/lang/Runtime.addShutdownHook:(Ljava/lang/Thread;)V
28: iconst_0
29: invokestatic #8; //Method java/lang/System.exit:(I)V
32: return
}
Run Code Online (Sandbox Code Playgroud)
字节码显然不同。我要么给出答案,要么其他了解 JVM 内部结构的人会提供帮助。