Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

클래스가 분명히 존재하는데도 Java에서 ClassNotFoundException이 발생하는 이유는?


Java에서 클래스를 로드하려고 할 때, 클래스 로더(ClassLoader)가 지정된 경로에서 해당 클래스를 찾지 못하면 ClassNotFoundException이 발생합니다.

이 예외는 Java 프로그램을 실행하는 도중이나, Class 클래스의 forName() 메서드 또는 ClassLoader 클래스의 loadClass() 메서드를 사용해 클래스를 명시적으로 로드할 때 발생할 수 있습니다. 이 두 메서드는 클래스 이름을 나타내는 문자열을 인자로 받아 지정된 클래스를 로드합니다.

따라서 이러한 메서드에 클래스 이름을 전달할 때는 반드시 다음 두 가지를 확인해야 합니다.

  • 메서드에 전달하는 클래스 이름이 정확해야 합니다. 패키지 이름까지 포함한 완전한 클래스 이름(FQCN)의 오타가 없어야 합니다.

  • 지정된 클래스(패키지 구조 포함)가 현재 작업 디렉터리에 존재하거나, 해당 경로가 환경 변수 classpath에 등록되어 있어야 합니다.

예제 코드

D:// 디렉터리에 Sample이라는 클래스를 생성하고 아래와 같이 컴파일했다고 가정해 보겠습니다.

package myPackage.example;
public class Sample {
    static {
        System.out.println("The class named Sample loaded successfully.........");
    }
}

컴파일

D:\>javac -d . Sample.java

위 명령을 실행하면 현재 디렉터리에 myPackage.example 패키지가 생성되고, 그 안에 Sample 클래스의 .class 파일이 만들어집니다. 따라서 이 클래스를 로드하려면 해당 파일이 동일한 디렉터리 구조 안에 있어야 하며, Class.forName() 또는 loadClass()에는 패키지 이름을 포함한 완전한 클래스 이름을 전달해야 합니다.

예제 코드

public class ClassNotFoundExample {
    public static void main(String args[]) {
        try {
            Class.forName("myPackage.exampl.Sample");
        }catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}

발생하는 예외

위 프로그램을 실행하면 패키지 이름의 철자(example이 아니라 exampl)가 잘못 입력되었기 때문에 다음과 같은 예외가 발생합니다.

D:\>java ClassNotFoundExample
java.lang.ClassNotFoundException: myPackage.exampl.Sample
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Unknown Source)
    at ClassNotFoundExample.main(ClassNotFoundExample.java:4)

다른 디렉터리에서 특정 클래스에 접근하려면 다음 중 하나를 대상으로 클래스패스(classpath)를 설정해야 합니다.

  • .class 파일이 포함된 폴더(최상위 패키지의 상위 디렉터리)

  • 또는 해당 클래스가 포함된 jar 파일

이번에는 철자 오류를 수정하고, E:// 디렉터리에 있는 Java 파일에서 해당 클래스를 로드하려고 한다고 가정해 보겠습니다.

예제 코드

public class ClassNotFoundExample {
    public static void main(String args[]) {
        try {
            Class.forName("myPackage.example.Sample");
        }catch (ClassNotFoundException ex) {
            ex.printStackTrace();
        }
    }
}

여전히 발생하는 예외

그러나 지정된 클래스의 .class 파일이 담긴 패키지(또는 이를 포함하는 jar 파일)가 현재 디렉터리에도 없고, 환경 변수 classpath의 경로 목록에도 등록되어 있지 않기 때문에 동일한 예외가 계속 발생합니다.

E:\>java ClassNotFoundExample
java.lang.ClassNotFoundException: myPackage.example.Sample
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Unknown Source)
    at ClassNotFoundExample.main(ClassNotFoundExample.java:4)

이 문제를 해결하려면 필요한 클래스가 들어 있는 패키지가 위치한 디렉터리, 즉 "D://"를 클래스패스로 설정한 뒤 프로그램을 다시 실행하면 됩니다. 그러면 클래스가 정상적으로 로드됩니다.

E:\>javac ClassNotFoundExample.java
E:\>java ClassNotFoundExample
The class named Sample loaded successfully.........