【发布时间】:2012-06-21 07:09:15
【问题描述】:
我在我们的一个项目中遇到了一个奇怪的问题。我们使用 JUnit 来运行我们的单元测试,前段时间,我们开始并行运行 pur 测试以加快执行速度。大多数时候,一切都很好,但有时,我们几乎所有的测试都会失败。在下一次运行时,它们都再次通过而没有更改任何代码。
这些错误似乎表明某些静态实例未正确初始化或在多线程情况下完成初始化之前未使用。 (我无法调试这个,因为调试时问题从未出现过 -> Heisenbug。)
抱歉,我无法提供显示该错误的最小工作示例,因为它在尝试重现时会消失。
具体的问题是:当像下面这样声明一个变量时,当另一个线程调用 foo() 或 bar() 时,是否有可能没有完成 a 或 b 的初始化?我认为可以保证在调用任何方法之前执行静态块。或者可能存在类加载器问题?还是 JRE 中的已知错误(我们目前停留在 1.6.0_21,我们的 IT 部门尚未提供更新的版本)?
class C {
private static final A a;
private static final B b;
static {
a = new A(...);
b = new B(...);
}
public static void foo() {
useA();
}
public static void bar() {
useB();
}
}
我确信它与硬件无关,因为它出现在来自不同制造商的不同机器上。测试正在使用服务器 vm。
谢谢,
阿克塞尔
【问题讨论】:
-
new A()或new B()是否启动新线程?您是否尝试过隔离问题并创建一个重现该问题的SSCCE? -
据我所知,将整个类与静态字段和方法一起使用是一种不好的做法,尤其是多线程。为什么不创建非静态类并将其存储在静态字段中?
-
这就是这里所做的。 a 和 b 是提供预先计算值的类的实例。这两个类都是不可变的,并且具有返回这些预先计算的值的方法。计算在各自的类构造函数中完成。访问时只需要检查参数、计算索引并返回包含先前计算值的数组元素。
标签: java initialization static-block