В моем приложении есть класс, как показано ниже:
public class Client {
public synchronized static print() {
System.out.println("hello");
}
static {
doSomething(); // which will take some time to complete
}
}
Этот класс будет использоваться в многопоточной среде, многие потоки могут вызывать метод Client.print () одновременно. Интересно, есть ли вероятность того, что thread-1 инициирует инициализацию класса, и до завершения инициализации класса thread-2 входит в метод print и выводит строку "hello"?
Я вижу это поведение в производственной системе (64-битная JVM + Windows 2008R2), однако я не могу воспроизвести это поведение с помощью простой программы в любых средах.
В спецификации языка Java, раздел 12.4.1 (http://java.sun.com/docs/books/jls/second_edition/html/execution.doc.html), это говорит:
Класс T или интерфейсный тип T будут инициализированы непосредственно перед первым появлением любого из следующего:
- T является классом, и создается экземпляр T.
- T является классом, и вызывается статический метод, объявленный T.
- Назначено статическое поле, объявленное T.
- Используется статическое поле, объявленное T, и ссылка на поле не является константой времени компиляции (§15.28). Ссылки на константы времени компиляции должны быть преобразованы во время компиляции в копию значения константы времени компиляции, поэтому использование такого поля никогда не вызывает инициализацию.
Согласно этому параграфу, инициализация класса будет происходить до вызова статического метода, однако неясно, должна ли инициализация класса быть завершена до вызова статического метода. JVM должна предписать завершение инициализации класса перед входом в его статический метод согласно моей интуиции, и некоторые мои эксперименты подтверждают мои предположения. Тем не менее, я видел противоположное поведение в другой среде. Может кто-нибудь пролить мне свет на это?
Любая помощь приветствуется, спасибо.