Java.Lang.NoClassDefFoundError 수정: 클래스 오류를 초기화할 수 없음
-
Java.Lang.NoClassDefFoundError: Could Not Initialize Class
오류가 있는 Java 프로그램 -
Java.Lang.NoClassDefFoundError: Could Not Initialize Class
오류의 가능한 원인 -
Java.Lang.NoClassDefFoundError: Could Not Initialize Class
오류를 근절하기 위한 솔루션
오늘은 또 다른 런타임 오류인 java.lang.noclassdeffounderror: could not initialize class
에 대해 알아보겠습니다. 먼저 이 오류가 있는 Java 프로그램을 살펴보고 가능한 원인에 대해 논의하고 이 오류를 일으키는 코드 줄을 파악합니다.
마지막으로 이 오류를 제거하는 솔루션에 대해서도 알아보겠습니다.
Java.Lang.NoClassDefFoundError: Could Not Initialize Class
오류가 있는 Java 프로그램
예제 코드:
public class PropHolder {
public static Properties prop;
static {
// write code to load the properties from a file
}
}
예제 코드:
import java.util.Properties;
public class Main {
public static void main(String[] args) {
// set your properties here
// save the properties in a file
// Referencing the PropHolder.prop:
Properties prop = PropHolder.prop;
// print the values of all properties
}
}
여기에는 PropHolder
및 Main
이라는 두 개의 .java
클래스가 있습니다. PropHolder
클래스는 지정된 파일에서 속성을 로드하고 Main
클래스는 속성을 설정하고 파일에 저장합니다.
또한 PropHolder
클래스의 prop
변수를 참조하여 모든 속성 값을 인쇄합니다.
이 Java 코드는 로컬 컴퓨터에서 실행할 때는 제대로 작동하지만 일부 스크립트를 사용하여 Linux 서버에 배포할 때는 작동하지 않습니다. 왜 그래야만하지? 이유를 알아 봅시다.
Java.Lang.NoClassDefFoundError: Could Not Initialize Class
오류의 가능한 원인
첫째, java.lang.NoClassDefFoundError
가 발생하는 것은 클래스가 누락되었음을 의미하는 것만이 아니라는 점을 기억하십시오. 그렇다면 java.lang.ClassNotFoundException
이 발생합니다.
또한 바이트 코드(.class
)가 누락되었음을 의미하지 않습니다(이 경우 java.lang.NoClassDefFoundError: classname
과 같은 오류가 발생함).
따라서 서버에서 java.lang.noclassdeffounderror: 클래스를 초기화할 수 없습니다
오류는 클래스 파일을 찾을 수 없음을 의미합니다. 아래에 나열된 여러 가지 이유로 인해 발생할 수 있습니다.
-
문제는
static
블록(정적
이니셜라이저라고도 함)에 있을 수 있습니다. 잡히지 않은 예외와 함께 나타나며 클래스를 로드하려고 시도하는 실제ClassLoader
까지 발생 및 전파됩니다. -
예외가
정적
블록으로 인한 것이 아닌 경우PropHolder.prop
라는정적
변수를 생성하는 동안일 수 있습니다. -
지정된 Java
CLASSPATH
에서Class
를 사용할 수 없을 수 있습니다. -
MANIFEST
파일의ClassPath
속성에Class
가 정의되지 않은 상태에서jar
명령을 사용하여 Java 프로그램을 실행했을 수 있습니다. -
이 오류는
CLASSPATH
환경 변수를 재정의하는 시작 스크립트로 인해 발생할 수 있습니다. -
또 다른 이유는 종속성이 없기 때문일 수 있습니다. 예를 들어
NoClassDefFoundError
가java.lang.LinkageError
의 하위 클래스이기 때문에 기본 라이브러리를 사용하지 못할 수 있습니다. -
정적
초기화 실패로 인해NoClassDefFoundError
가 발생했을 가능성이 있으므로log
파일에서java.lang.ExceptionInInitializerError
를 찾을 수도 있습니다. -
J2EE 환경에서 작업하는 경우 다른
ClassLoaders
에서Class
의 가시성으로 인해java.lang.NoClassDefFoundError
오류가 발생할 수 있습니다. -
간혹 JRE/JDK 버전 오류로 인해 발생하는 경우가 있습니다.
-
예를 들어 OpenJDK 버전 8.x.x를 사용하여 시스템에서 무언가를 컴파일할 때도 발생할 수 있습니다. 푸시/커밋하지만 다른 사람이
JAVA_HOME
을 일부 11.x JDK 버전으로 구성했습니다.여기에서
ClassNotFoundError
,NoClassDefFoundError
등을 얻을 수 있습니다. 따라서 프로그램이 컴파일된 JDK를 확인하는 것이 좋습니다.
Java.Lang.NoClassDefFoundError: Could Not Initialize Class
오류를 근절하기 위한 솔루션
우리의 경우 클래스를 읽으려고 할 때 클래스 정의를 읽는 동안 ClassLoader
에서 오류가 발생했습니다. 따라서 정적 초기화 안에 try-catch
블록을 넣으면 문제가 해결됩니다.
그곳에서 일부 파일을 읽으면 로컬 환경과 다를 수 있음을 기억하십시오.
예제 코드:
// import libraries
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
// PropHolder Class
public class PropHolder {
// static variable of type Properties
public static Properties prop;
// static block, which loads the properties
// from the specified file
static {
try {
InputStream input = new FileInputStream("properties");
prop = new Properties();
prop.load(input);
} catch (FileNotFoundException ex) {
Logger.getLogger(PropHolder.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PropHolder.class.getName()).log(Level.SEVERE, null, ex);
}
} // end static block
} // end PropHolder class
위의 클래스에서 정적
블록에서 사용하는 속성
유형의 prop
라는 정적 변수를 만들었습니다. 정적
블록 내에서 파일 시스템의 지정된 파일에서 입력 바이트를 가져오는 FileInputStream
객체를 생성했습니다.
다음으로 지정된 파일에서 속성을 로드하는 데 사용되는 Properties
클래스의 생성자를 호출하여 prop
변수를 초기화했습니다. 이 정적
블록은 애플리케이션을 실행한 후에만 실행된다는 점을 기억하십시오.
예제 코드:
// import libraries
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;
// Main Class
public class Main {
// main()
public static void main(String[] args) {
/*
instantiate the Properties class, set various
properties and store them in a given file
*/
Properties prop = new Properties();
prop.setProperty("db.url", "localhost");
prop.setProperty("db.user", "user");
prop.setProperty("db.password", "password");
try {
OutputStream output = new FileOutputStream("properties");
prop.store(output, null);
} catch (FileNotFoundException ex) {
Logger.getLogger(PropHolder.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(PropHolder.class.getName()).log(Level.SEVERE, null, ex);
}
/*
reference the `PropHolder.prop` to access the values of
the properties that we set previously
*/
Properties obj = PropHolder.prop;
System.out.println(obj.getProperty("db.url"));
System.out.println(obj.getProperty("db.user"));
System.out.println(obj.getProperty("db.password"));
} // end main()
} // end Main
Main
클래스에서 Properties
클래스를 인스턴스화하여 다양한 속성에 대한 값을 설정하고 지정된 파일에 저장합니다. 다음으로 PropHolder.prop
를 참조하여 db.url
, db.user
및 db.password
속성 값에 액세스하고 프로그램 출력 콘솔에 다음과 같이 인쇄합니다.
출력:
localhost
user
password