简体   繁体   English

java:在类初始化期间初始化同一个类的静态字段

[英]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),该代码在代码中描述,但实际发生了什么?

  1. During class initialization, static fields are initialized from up to down; 在类初始化期间,静态字段从上到下初始化;
  2. we trying to init "tariffModelManager" field... 我们试图初始化“tariffModelManager”字段......
  3. calling method getInstance(), that checks _instance field (but it is not initialized!); 调用方法getInstance(),它检查_instance字段(但它没有被初始化!);
  4. then we must execute constructor of this class; 那么我们必须执行这个类的构造函数;
  5. if _instance field has been initialized in constructor, can it be set to null in static fields initialization sequence? 如果_instance字段已在构造函数中初始化,是否可以在静态字段初始化序列中将其设置为null?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM