看起来在启动应用程序时发生了死锁。 我有jstack文件,其中我发现一个线程调用TariffModelManager。< clinit>方法和其他多个线程调用TariffModelManager.getInstance()方法。 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;
}
...
}
我认为,通过调用getInstance()方法来初始化静态字段是一个明显的错误,其中检查了另一个字段(_instance),该代码在代码中有所描述,但实际发生了什么?
我的问题不是如何解决这个问题,而是描述执行此代码时发生的事情!
更新 Here我发现了详细的类初始化过程,但仍然不清楚,在哪个顺序" tariffModelManager"和" _instance"字段已初始化。
谢谢!
答案 0 :(得分:1)
您可以通过在两个静态字段上放置字段断点来验证发生了什么。
我稍微修改了你的样本:
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);
}
}
这是输出:
From Constructor: TariffModelManager@ea4a92b
Creating new instance: TariffModelManager@ea4a92b
From Constructor: TariffModelManager@3c5a99da
tariffModelManager: TariffModelManager@ea4a92b
_instance: TariffModelManager@3c5a99da
首先初始化静态字段tariffModelManager
。调用getInstance
方法时_instance
为空 - 即默认值且尚未初始化。然后在该方法内初始化,并将值分配给tariffModelManager
。然后根据静态初始化顺序再次重新初始化: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.
这很有趣,因为
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;
}
}
是无效的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;
}
}