java - 在这种情况下,FindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER' 是否可以安全地忽略

标签 java static initialization findbugs

我需要使用一个库,该库对静态值进行了危险的初始化(示例中的类已被精简到最少):

public TheirBaseClass {
    public static String PathToUse = null;

    public BaseClass(){
        PathToUse = "Configured";

        // ... 
        // do some other stuff with other side effects 
        // ...
    }
}

我有一个案例,我尝试在不实例化类的情况下读取值 ConfigValue(以避免一些副作用)。

Paths.get(TheirBaseClass.PathToUse).toFile()....

这会导致NullPointerException

因为我需要使用此类,所以我希望继承它,并尝试采取措施以确保在访问静态时已进行初始化。

public MyBaseClass extends TheirBaseClass{

    private static final AtomicBoolean isInitialized = new AtomicBoolean(false);

    static {
        MyBaseClass.Initialize();
    }

    public static void Initialize(){
        // FindBugs does not like me synchronizing on a concurrent object
        synchronized(isInitialized){
            if( isInitialized.get() ){
                return;
            }
            new TheirBaseClass();
            isInitialized.set(true);
        }
    }

    public MyBaseClass(){
        super();
    }

}

这让我能够

MyBaseClass.Initialize();
Paths.get(MyBaseClass.PathToUse).toFile()....

这似乎工作得相当好(并解决了我们一直遇到的其他一些幻觉缺陷)。它允许irBaseClass自然地发挥作用,同时允许我在可能需要的几种情况下安全地强制初始化。

但是,当我针对此代码运行 FindBugs 时,我得到 JLM_JSR166_UTILCONCURRENT_MONITORENTER。阅读描述后,我同意使用 AtomicBoolean 可能很危险,因为其他人可以更改该值,但是......

  1. 我认为在这种情况下可以忽略(但有疑问)
  2. 我通常更喜欢重写代码而不是放置忽略标记

我真的在做一些危险的事情吗(只是没有看到)?有一个更好的方法吗?

不幸的是,使用不同的TheirBaseClass不是一种选择。

相关

最佳答案

您可能会发现适应 lazy holder idiom 更容易:

public MyBaseClass {
  private static class Initializer {
    static {
      new TheirBaseClass();
    }

    // Doesn't actually do anything; merely provides an expression
    // to cause the Initializer class to be loaded.
    private static void ensureInitialized() {}
  }

  {
    Initializer.ensureInitialized();
  }

  // Rest of the class.
}

这利用了类加载仅发生一次并且是同步的这一事实(在单个类加载器内)。仅当您实例化 MyBaseClass 时才会发生。

关于java - 在这种情况下,FindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER' 是否可以安全地忽略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39149166/

相关文章:

java - 如何从类 token 访问子类静态方法?

php - 使用键名但空值初始化关联数组

Java Bitset 初始化

c - C中的大结构初始化

java - 使用 hashmap 和同步方法调用的简单缓存机制

java - Hibernate:查询在 CollectionOfElements 中包含指定元素的实体?

java - 尝试查找素数时出现意外输出 - Java

java - Jtable1 header 提供给 Jtable2,具有排序和边距调整等属性

java - ClassNotFoundException:奇怪的行为

javascript - ASP.NET:UpdateProgress 不适用于具有 ClientIDMode ="Static"的控件