Yüksek derecede eşzamanlı singleton sınıfı için birim testleri ile uğraşırken, aşağıdaki garip davranışa rastladım (JDK 1.8.0_162'de test edildi):
private static class SingletonClass {
static final SingletonClass INSTANCE = new SingletonClass(0);
final int value;
static SingletonClass getInstance() {
return INSTANCE;
}
SingletonClass(int value) {
this.value = value;
}
}
public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
System.out.println(SingletonClass.getInstance().value); // 0
// Change the instance to a new one with value 1
setSingletonInstance(new SingletonClass(1));
System.out.println(SingletonClass.getInstance().value); // 1
// Call getInstance() enough times to trigger JIT optimizations
for(int i=0;i<100_000;++i){
SingletonClass.getInstance();
}
System.out.println(SingletonClass.getInstance().value); // 1
setSingletonInstance(new SingletonClass(2));
System.out.println(SingletonClass.INSTANCE.value); // 2
System.out.println(SingletonClass.getInstance().value); // 1 (2 expected)
}
private static void setSingletonInstance(SingletonClass newInstance) throws NoSuchFieldException, IllegalAccessException {
// Get the INSTANCE field and make it accessible
Field field = SingletonClass.class.getDeclaredField("INSTANCE");
field.setAccessible(true);
// Remove the final modifier
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
// Set new value
field.set(null, newInstance);
}
Main () yönteminin son 2 satırı INSTANCE değerine katılmıyor - tahminim JIT, alan statik olduğu için yöntemden tamamen kurtuldu. Son anahtar kelimenin kaldırılması kod çıktısını doğru değerler yapar.
Singletons için sempatinizi (veya eksikliğinizi) bir kenara bırakarak ve böyle bir yansımayı kullanmanın sorun istediğini bir dakika unutmak - JIT optimizasyonlarının suçlanacağı yönündeki varsayım doğru mu? Öyleyse - yalnızca statik son alanlarla sınırlı mı?
static final
alana sahip bir sınıfınız var . Bunun yanı sıra, bu yansıma saldırısının JIT veya eşzamanlılık nedeniyle kırılıp kırılmayacağı önemli değildir.