考虑以下代码:
如果假设静态初始化提供了内存屏障是可靠的(我相信是这样),那么这必然会指向JDK的错误吗?你能想到除了JDK bug之外的原因吗?
public class Text {
private static ThreadLocal<CharsetEncoder> encoderFactory =
new ThreadLocal<CharsetEncoder>() {
@Override
protected CharsetEncoder initialValue() {
return Charset.forName("UTF-8").newEncoder().
onMalformedInput(CodingErrorAction.REPORT).
onUnmappableCharacter(CodingErrorAction.REPORT);
}
};
public static ByteBuffer encode(String string, boolean replace)
throws CharacterCodingException {
CharsetEncoder encoder = encoderFactory.get();
...
}
}
在并发情况下,encode()
中访问encoderFactory
的代码行是否会抛出NullPointerException
?
是的,我很清楚,在这种情况下,将encoderFactory
声明为final可以使这个问题变得有点无关紧要。
然而,我的兴趣在于,上述代码是否仍然安全地发布了encoderFactory
。如果我理解JLS 12.4,应该是这样的。静态初始化的步骤似乎不会留下任何线程会看到未初始化状态的静态字段(即没有 happens-before),一旦它看到类被初始化。我认为JLS让它相当清楚,静态初始化形成了一个内存屏障。
NullPointerException
,我们最终通过将此字段设置为final来修复它。虽然这样做肯定是好的,但我仍然感到困惑,如何才能看到这种模式的空指针,否则可能存在更大的问题,因为这可能意味着任何非final静态字段的初始赋值都可能不可见。如果假设静态初始化提供了内存屏障是可靠的(我相信是这样),那么这必然会指向JDK的错误吗?你能想到除了JDK bug之外的原因吗?