자바 개발을 하다 보면 런타임에 클래스를 찾지 못해 발생하는 두 가지 대표적인 오류, ClassNotFoundException과 NoClassDefFoundError를 마주하게 됩니다. 두 오류 모두 JVM이나 클래스로더(ClassLoader)가 실행 시점에 필요한 클래스를 로딩하지 못할 때 발생하지만, 성격과 발생 원인은 분명히 다릅니다.
ClassNotFoundException은 컴파일러가 반드시 처리하도록 요구하는 체크 예외(checked exception)이며, NoClassDefFoundError는 처리 여부가 선택적인 언체크(unchecked) 범주에 속하는 Error입니다.
클래스로더는 서로 다른 소스에서 클래스를 불러오는데, 이 과정에서 필요한 JAR 파일이 누락되었거나 클래스패스(classpath) 설정이 잘못되면 런타임에 클래스를 로드하지 못해 문제가 발생할 수 있습니다.
ClassNotFoundException란?
ClassNotFoundException은 리플렉션(Reflection)을 사용해 런타임에 동적으로 클래스를 로드하려 할 때, 해당 클래스 파일이 존재하지 않으면 발생합니다. 클래스를 런타임에 로드하기 때문에 컴파일 시점에는 어떠한 검사도 이루어지지 않습니다.
ClassNotFoundException 예제
public class ClassNotFoundExceptionTest {
public static void main(String[] args) {
try {
Class.forName("Test");
} catch (ClassNotFoundException cnfe) {
System.err.println("존재하지 않는 클래스를 검색하려고 합니다. " + cnfe);
}
}
}
실행 결과
존재하지 않는 클래스를 검색하려고 합니다. java.lang.ClassNotFoundException: Test
NoClassDefFoundError란?
NoClassDefFoundError는 특정 클래스가 클래스패스에 있는 상태로 컴파일되었지만, 실행 시점에는 같은 클래스를 더 이상 찾을 수 없을 때 발생합니다. 가장 흔한 원인은 JAR 파일의 누락입니다. 자바 API 문서에 따르면 "현재 실행 중인 클래스가 컴파일될 당시에는 검색 대상 클래스의 정의가 존재했지만, 더 이상 그 정의를 찾을 수 없다"는 의미입니다.
NoClassDefFoundError 예제
class Test1 {
public void show() {
System.out.println("show() 메서드 호출");
}
}
public class Test2 {
public static void main(String[] args) {
Test1 t = new Test1();
t.show();
}
}
위 코드를 컴파일하면 Test1.class와 Test2.class 두 개의 클래스 파일이 생성됩니다. 이후 Test2를 실행하기 전에 Test1.class 파일을 삭제하면 아래와 같이 NoClassDefFoundError가 발생합니다.
실행 결과
Exception in thread "main" java.lang.NoClassDefFoundError: Test1
at Test2.main(Test2.java:9)
핵심 차이점 비교
| 구분 | ClassNotFoundException | NoClassDefFoundError |
|---|---|---|
| 유형 | 체크 예외(checked exception) | Error (언체크) |
| 발생 시점 | 리플렉션 등으로 런타임에 클래스를 명시적으로 로드할 때 | 컴파일 시점에는 존재했으나 런타임에 클래스가 없을 때 |
| 대표 원인 | Class.forName(), loadClass() 등으로 존재하지 않는 클래스 로드 시도 | JAR 파일 누락, 클래스패스 변경 또는 오류 |
| 처리 방법 | try-catch로 반드시 처리해야 함 | 처리는 선택 사항 |
정리하면, ClassNotFoundException은 런타임에 동적으로 클래스를 로드하려다 실패한 경우의 예외이고, NoClassDefFoundError는 컴파일 당시에는 있었던 클래스가 실행 환경에서 사라졌을 때 발생하는 에러입니다. 두 오류의 발생 조건을 정확히 이해하면 클래스패스 관련 문제를 훨씬 빠르게 진단하고 해결할 수 있습니다.