[英]java: initialization of static fields of the same class during class initialization
It looks like deadlock happened during starting the application. 看起来在启动应用程序时发生了死锁。 I have jstack file in which i found that one thread call TariffModelManager.<clinit> method and there are others multiple threads calling TariffModelManager.getInstance() method.
我有jstack文件,其中我发现一个线程调用TariffModelManager。<clinit>方法,还有其他多个线程调用TariffModelManager.getInstance()方法。 The code of TariffModelManager following:
TariffModelManager的代码如下:
public class TariffModelManager{
...
private static final TariffModelManager tariffModelManager = TariffModelManager.getInstance();
...
private static volatile TariffModelManager _instance;
private TariffModelManager(){}
public static TariffModelManager getInstance() {
if(_instance == null) {
synchronized(TariffModelManager.class) {
if(_instance == null) _instance = new TariffModelManager();
}
}
return _instance;
}
...
}
I think, this is an apparent mistake to initialize static field by calling getInstance() method in which checked another field (_instance), that described bellow in the code, but what is really happened? 我认为,通过调用getInstance()方法来初始化静态字段是一个明显的错误,在该方法中检查了另一个字段(_instance),该代码在代码中描述,但实际发生了什么?
My question is not how to solve this, but describe what is really happened when this code executed! 我的问题不是如何解决这个问题,而是描述这段代码执行时真正发生的事情!
UPDATE: Here i found detailed class initialization procedure, but it is still not clear, in which order "tariffModelManager" and "_instance" fields are initialized. 更新: 这里我发现了详细的类初始化过程,但仍然不清楚,“tariffModelManager”和“_instance”字段的初始化顺序。
Thanks! 谢谢!
You can verify what's happening by putting field breakpoints on the two static fields. 您可以通过在两个静态字段上放置字段断点来验证发生了什么。
I've modified your sample a bit: 我稍微修改了你的样本:
class TariffModelManager {
private static final TariffModelManager tariffModelManager = TariffModelManager.getInstance();
private static volatile TariffModelManager _instance = new TariffModelManager();
private TariffModelManager() {
System.out.println("From Constructor: " + this);
}
public static TariffModelManager getInstance() {
if (_instance == null) {
synchronized (TariffModelManager.class) {
if (_instance == null) {
_instance = new TariffModelManager();
System.out.println("Creating new instance: " + _instance);
}
}
}
return _instance;
}
public static void main(String[] args) {
TariffModelManager.getInstance();
System.out.println("tariffModelManager: " + TariffModelManager.tariffModelManager);
System.out.println("_instance: " + TariffModelManager._instance);
}
}
And here is the output: 这是输出:
From Constructor: TariffModelManager@ea4a92b
Creating new instance: TariffModelManager@ea4a92b
From Constructor: TariffModelManager@3c5a99da
tariffModelManager: TariffModelManager@ea4a92b
_instance: TariffModelManager@3c5a99da
The static field tariffModelManager
is initialized first. 首先初始化静态字段
tariffModelManager
。 When the getInstance
method is called _instance
is null - ie the default value and not initialized yet. 当调用
getInstance
方法时, _instance
为null - 即默认值并且尚未初始化。 Then it is initialized inside that method and the value is assigned to tariffModelManager
as well. 然后在该方法内初始化,并将值分配给
tariffModelManager
。 Then it is reinitialized again according to the static initialization order: Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block. 然后根据静态初始化顺序再次重新初始化: 接下来,按文本顺序执行类的类变量初始值设定项和静态初始值设定项,或接口的字段初始值设定项,就好像它们是单个块一样。
This is funny, because 这很有趣,因为
class TariffModelManager {
private static final TariffModelManager tariffModelManager = _instance;
private static volatile TariffModelManager _instance = new TariffModelManager();
private TariffModelManager() {
System.out.println("From Constructor: " + this);
}
public static TariffModelManager getInstance() {
return _instance;
}
}
is invalid java, but the static methods gives you a way to "work around" it (well tariffModelManager will be null, not really what's intended, but still compiles): 是无效的java,但静态方法为您提供了一种“解决”它的方法(以及tariffModelManager将为null,不是真正意图,但仍然编译):
class TariffModelManager {
private static final TariffModelManager tariffModelManager = getInstance();
private static volatile TariffModelManager _instance = new TariffModelManager();
private TariffModelManager() {
System.out.println("From Constructor: " + this);
}
public static TariffModelManager getInstance() {
return _instance;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.