Jest bezpieczna bo ładowaniue statycznych klas/instancji odbywa się podczas "inicjalizacji JVM" i już na tym etapie tworzona jest instancja singletona.
Nie. Ładowanie klas odbywa się podczas ich pierwszego użycia. Możesz sobie printlna wstawić w konstruktor klasy i sprawdzić kiedy się wywołuje. Dopóki jej nie ruszysz to nic się nie załaduje.
W normalnej aplikacji nawet jeśli masz 5 gigabajtów JARów na classpathu, a używasz tylko 100 megabajtów klas to tylko 100 megabajtów klas zostanie załadowanych. Jeżeli natomiast używasz jakichś skanerów classpatha np ze Springa to wszystko się może zdarzyć i możliwe, że Spring niepotrzebnie załaduje te 5 gigabajtów klas do pamięci. Chociaż z drugiej strony można analizować klasy bez ich ładowania, więc być może Spring ma jakiś dekoder plików .class, który nie używa ClassLoaderów.
Racja, teraz rozumiem, dzięki :) A możesz mi jeszcze wytłumaczyć dlaczego poniższa implementacja jest bezpieczna wątkowo?
public class SingletonStaticHolder {
private SingletonStaticHolder() {
}
private static class Holder {
private static final SingletonStaticHolder INSTANCE = new SingletonStaticHolder();
}
public static SingletonStaticHolder getInstance() {
return Holder.INSTANCE;
}
}
Załóżmy, że dwa wątki równocześnie wywołują metodę getInstance(). Ponieważ klasa Holder nie została jak dotąd użyta następuje jej ładowanie a przy okazji inicjalizacja INSTANCE. Czy drugi wątek również może wykonać w tym samym czasie ładowanie klasy? Spodziewam się, że nie rozumiem dlaczego...
Ładowanie klas w JVMie jest bezpieczne wątkowo.
https://docs.oracle.com/javase/8/docs/api/java/lang/ClassLoader.html#loadClass-java.lang.String-boolean-
Unless overridden, this method synchronizes on the result of getClassLoadingLock method during the entire class loading process.