Чем отличаются ClassNotFoundException и NoClassDefFoundError

Вопрос проверяет, понимаете ли вы разницу между поиском класса по имени и его использованием после успешной загрузки — то есть, что происходит на разных этапах жизненного цикла classloading.

ClassNotFoundException бросает сам classloader, когда явно просят найти класс по имени и не находят его в classpath. Обычно это происходит внутри Class.forName(...), ClassLoader.loadClass(...) или при десериализации, если библиотека не подключена в runtime.

NoClassDefFoundError — это Error, не Exception, и появляется в другой момент: класс был доступен и успешно загружен при первом обращении, но при повторном использовании (или в другом потоке) classloader не может найти .class файл — например, его убрали из classpath между компиляцией и запуском, или статический инициализатор упал при первой загрузке.

try { Class.forName("com.example.OldService"); } catch (ClassNotFoundException e) { // класса нет в classpath вообще }

Частый follow-up: «класс точно есть в classpath, но всё равно NoClassDefFoundError — почему?» Ответ обычно в статическом блоке инициализации: если static-инициализатор бросил исключение при первой загрузке класса, JVM помечает класс как «error» и при каждой следующей попытке использовать его кидает NoClassDefFoundError — даже если .class файл никуда не пропадал.

Один Error и один Exception описывают два разных провала classloading, и путать их на собеседовании — сигнал, что механизм не разобран, а запомнено только название.

Тренажёр: 600 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки