在这种情况下可以安全地忽略 FindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER'
is FindBugs 'JLM_JSR166_UTILCONCURRENT_MONITORENTER' safe to ignore in this case
我有一个我需要使用的库,它对静态值进行了危险的初始化(对于示例,classes 已被简化为最小值):
public TheirBaseClass {
public static String PathToUse = null;
public BaseClass(){
PathToUse = "Configured";
// ...
// do some other stuff with other side effects
// ...
}
}
我有一个案例,我试图从值 ConfigValue
读取而不实例化 class(以避免一些副作用)。
Paths.get(TheirBaseClass.PathToUse).toFile()....
这会导致 NullPointerException
因为我需要使用这个 class,所以我希望继承它,并尝试采取行动以确保在访问静态时已进行初始化。
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()....
这似乎工作得相当好(并解决了我们一直遇到的其他一些幻影缺陷)。它允许 TheirBaseClass
自然地运行,同时允许我在我可能需要的几种情况下安全地强制初始化。
然而,当我针对此代码 运行 FindBugs 时,我得到 JLM_JSR166_UTILCONCURRENT_MONITORENTER
。阅读描述后,我同意 AtomicBoolean
的使用可能很危险,因为其他人可以更改该值,但是...
- 我认为在这种情况下忽略它是安全的(但有疑问)
- 我通常更喜欢重写代码而不是放置一个忽略标记
我真的在做危险的事情吗(只是没看到)?有一个更好的方法吗?
不幸的是,使用不同的 TheirBaseClass
不是一种选择。
相关
- Are Java static initializers thread safe?
您可能会发现更容易适应 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.
}
这利用了 class 加载仅发生一次并且是同步的这一事实(在单个 class 加载程序中)。它仅在您实例化 MyBaseClass
.
时发生
我有一个我需要使用的库,它对静态值进行了危险的初始化(对于示例,classes 已被简化为最小值):
public TheirBaseClass {
public static String PathToUse = null;
public BaseClass(){
PathToUse = "Configured";
// ...
// do some other stuff with other side effects
// ...
}
}
我有一个案例,我试图从值 ConfigValue
读取而不实例化 class(以避免一些副作用)。
Paths.get(TheirBaseClass.PathToUse).toFile()....
这会导致 NullPointerException
因为我需要使用这个 class,所以我希望继承它,并尝试采取行动以确保在访问静态时已进行初始化。
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()....
这似乎工作得相当好(并解决了我们一直遇到的其他一些幻影缺陷)。它允许 TheirBaseClass
自然地运行,同时允许我在我可能需要的几种情况下安全地强制初始化。
然而,当我针对此代码 运行 FindBugs 时,我得到 JLM_JSR166_UTILCONCURRENT_MONITORENTER
。阅读描述后,我同意 AtomicBoolean
的使用可能很危险,因为其他人可以更改该值,但是...
- 我认为在这种情况下忽略它是安全的(但有疑问)
- 我通常更喜欢重写代码而不是放置一个忽略标记
我真的在做危险的事情吗(只是没看到)?有一个更好的方法吗?
不幸的是,使用不同的 TheirBaseClass
不是一种选择。
相关
- Are Java static initializers thread safe?
您可能会发现更容易适应 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.
}
这利用了 class 加载仅发生一次并且是同步的这一事实(在单个 class 加载程序中)。它仅在您实例化 MyBaseClass
.