Я понимаю, что правило для статических инициализаторов состоит в том, что они выполняются только каждый раз, после загрузки байт-кода класса и перед выполнением любого статического метода или созданием экземпляра первого объекта из класса. JLS гарантирует, что эта инициализация будет завершена. Чтобы гарантировать, что эта гарантия верна, JLS также указывает, что код не мог быть внезапно завершен (как четко указано в другом ответе).
Обратите внимание, что можно загрузить байт-код без его инициализации; см. Class.forName (String, boolean, ClassLoader) метод. Если параметр boolean
равен false
, это загрузит класс, но не инициализирует его. Программист все еще может поразмышлять над тем, чтобы найти информацию об этом классе без инициализации. Однако, как только вы попытаетесь использовать класс напрямую, вызывая статический метод или создавая экземпляр экземпляра, JVM сначала приступит к его инициализации.
Если какой-либо из статических инициализаторов завершается внезапно - что может произойти с RuntimeException
, класс останется в недопустимом состоянии. В первый раз JVM сгенерирует ExceptionInInitializeError
(обратите внимание, что Error
означает, что он считается внутренним сбоем). С этого момента будет невозможно использовать класс - пытаясь вызвать статический метод или создав объект, вместо этого вы получите NoClassDefFoundError
.
Единственный способ выхода из этой ситуации без перезапуска JVM - это если вы используете ClassLoader
s и можете заменить загрузчик классов на отказавший класс и перестроить класс или переинициализировать в другой среде (возможно, в других системных свойствах) , но тогда программа должна быть хорошо подготовлена к такой ситуации.