클래스 로딩 예외
애플리케이션을 개발하거나 설치된 애플리케이션을 시작할 때 발생하는 클래스 로딩 오류 유형
ClassCastException
다음과 같은 경우 클래스 캐스트 예외가 발생하며 이 예외는 다음 조치로 정정할 수 있습니다.
- 소스 오브젝트 유형이 대상 클래스 (유형)의 인스턴스가 아닙니다.
- 소스 오브젝트 (클래스)를 로드한 클래스 로더가 대상 클래스를 로드한 클래스 로더와 다릅니다.
- 애플리케이션이 한정 조작을 수행하는 데 실패하거나 제대로 수행하지 못했습니다.
- 소스 오브젝트 유형이 대상 클래스 (유형)의 인스턴스가 아닙니다.
- 일반적인 클래스 캐스트 예외입니다. 소스 오브젝트 클래스의 클래스 서명을
검사한 다음 이의 상위 구조에 대상 클래스가 포함되어 있고 소스 오브젝트 클래스가
대상 클래스와 다른지 확인하여 캐스트 문의 소스 오브젝트가 대상 클래스(유형)의
인스턴스가 아닌지 여부를 진단할 수 있습니다. 코드에 단순 인쇄문을 삽입하여
클래스 정보를 얻을 수 있습니다. 예를 들어, 다음과 같습니다.
또는 javap 명령을 사용하십시오. 예를 들어, 다음과 같습니다.System.out.println( source.getClass().getName() + “:” + target.getClass().getName() );
javap java.util.HashMap Compiled from "HashMap.java" public class java.util.HashMap extends java.util.AbstractMap implements java.util.Map,java.lang.Cloneable,java.io.Serializable {
- 소스 오브젝트 (클래스)를 로드한 클래스 로더가 대상 클래스를 로드한 클래스 로더와 다릅니다.
- 소스 오브젝트의 유형이 대상 클래스의 인스턴스라고 가정하면 소스 오브젝트의
클래스를 로드한 클래스 로더가 대상 클래스를 로드한 클래스와 다른 경우 클래스
캐스트 예외가 발생합니다. 이 조건은 대상 클래스가 WebSphere® Application Server
런타임 환경에 있는 둘 이상의 클래스 로더의 클래스 경로에서 볼 수 있을 때
발생할 수 있습니다. 이 문제점을 정정하려면 다음과 같이 클래스 로더 관련 문제점을
진단하는 데 사용되는 검색 및 클래스 이름별 검색 콘솔 페이지를 사용하십시오.
- 검색 페이지에 액세스하십시오. 을 클릭하여
- 검색 유형으로는 클래스/패키지를 선택하십시오.
- 검색 용어에는 두 개의 클래스 로더가 로드하는 클래스의 이름을 입력하십시오.
- 확인을 클릭하십시오. 클래스 이름별 검색 페이지가 표시되어
클래스를 로드하는 모든 클래스 로더가 나열됩니다.
하나 이상의 클래스 로더가 나열되는 경우 대상 클래스가 하나 이상의 클래스 로더에 의해 로드된 것입니다. 소스 오브젝트가 대상 클래스의 인스턴스이므로, 소스 오브젝트 클래스를 로드한 클래스 로더가 대상 클래스를 로드한 클래스 로더와 다릅니다.
- 클래스 로더 뷰어 페이지로 리턴하고 클래스 경로를 검사하여 두 개의 다른 클래스 로더가 해당 클래스를 로드하는 이유를 판별하십시오.
- 해당 클래스가 올바른 클래스 로더에만 표시되도록 코드를 정정하십시오.
- 애플리케이션이 한정 조작을 수행하는 데 실패하거나 제대로 수행하지 못했습니다.
- 클래스 캐스트 예외는 애플리케이션이 엔터프라이즈 Bean(EJB) 오브젝트를
해석할 때 애플리케이션 코드가 필요한 대로 한정 조작을 수행하지 않기
때문에 발생합니다. 애플리케이션은 원격 오브젝트를 찾아본 후 한정
조작을 수행해야 합니다. 애플리케이션을 검사하여 원격 오브젝트를 찾는지와 만일 찾는다면
찾은 결과가 한정 메소드로 제출되는지 여부를 판별하십시오.
한정 메소드는 EJB 2.0 프로그래밍 모델에 따라 호출되어야 합니다. 특히 한정 메소드에 제출된 대상 클래스는 EJB의 정확히 일치하는 최하위 파생이어야 합니다. 이는 WebSphere Application Server 런타임 환경에 클래스 캐스트 예외를 발생시킵니다. 애플리케이션을 검사하여 한정 메소드에 제출된 대상 클래스가 정확히 일치하는 EJB 유형이 아닌 지정되는 EJB의 수퍼인터페이스인지 여부를 판별하고 만일 그렇다면 정확히 일치하는 EJB 인터페이스를 가진 한정 메소드를 호출하도록 애플리케이션을 수정하십시오.
마지막으로 한정 조작 중에 클래스 캐스트 예외가 발생하는 경우 한정 메소드가 로컬 엔터프라이즈 Bean이 아닌 원격 EJB 검색의 결과에 적용되고 있는지 확인하십시오. 로컬 검색에는 한정 조작이 사용되지 않습니다. 애플리케이션 또는 모듈 배치 디스크립터를 검사하여 한정하는 오브젝트가 로컬 오브젝트가 아닌지 확인하십시오.
ClassNotFoundException
다음과 같은 경우 클래스를 찾을 수 없음 예외가 발생하며 이 예외는 다음 조치로 정정할 수 있습니다.
- 클래스가 컨텍스트 클래스 로더의 논리 클래스 경로에 보이지 않습니다.
- 찾을 수 없는 클래스가 현재 스레드와 연관된 클래스 로더의 논리 클래스
경로에 없습니다. 논리 클래스 경로는 로드 조작이 클래스 로더에서 호출될 때
검색되는 모든 클래스 경로의 누적입니다.
이 문제점을 정정하려면 다음과 같이 검색 페이지를 사용하여 클래스 이름별로 또는 JAR(Java™
Archive) 이름별로 검색하십시오.
- 검색 페이지에 액세스하십시오. 을 클릭하여
- 검색 유형으로는 클래스/패키지를 선택하십시오.
- 검색 용어에는 찾을 수 없는 클래스의 이름을 입력하십시오.
- 확인을 클릭하십시오. 클래스 이름별 검색 페이지가 표시되어 클래스를 로드하는 모든 클래스 로더가 나열됩니다.
- 페이지를 검사하여 클래스가 목록에 있는지 확인하십시오.
- 클래스가 목록에 없는 경우 검색 페이지로 돌아가십시오. 검색 용어에는 클래스의 .jar 파일 이름을 입력하고 검색 유형으로는 JAR/디렉토리를 선택하십시오.
- 확인을 클릭하십시오. 경로별 검색 페이지가 표시되어 JAR 파일이 들어 있는 모든 디렉토리가 나열됩니다.
JAR 파일이 목록에 없는 경우 논리 클래스 경로에 클래스가 없거나 판독 불가 또는 대체 클래스가 이미 로드된 경우입니다. 로드할 수 있는 위치로 클래스를 이동하십시오.
- 애플리케이션이 클래스 로더 API를 올바르지 않게 사용합니다.
- 애플리케이션은 클래스 로더의 인스턴스를 얻을 수 있고 해당 클래스 로더에서
loadClass를 호출하거나 해당 클래스 로더를 사용하여 Class.forName(class_name, initialize, class_loader)을
호출할 수 있습니다. 애플리케이션이 클래스 로더 API(Application Programming
Interface)를 잘못 사용하고 있을 수 있습니다. 예를 들어 클래스 이름이
잘못되었거나 클래스가 해당 클래스 로더의 논리 클래스 경로에 보이지 않거나
올바르지 않은 클래스 로더가 사용되었습니다.
이 문제점을 정정하려면 클래스 존재 여부와 애플리케이션이 클래스 로더 API를 제대로 사용하는지 여부를 판별하십시오. 클래스가 컨텍스트 클래스 로더의 논리 클래스 경로에 보이지 않습니다에 있는 단계를 따라 클래스가 로드되어 있는지 판별하십시오. 클래스가 로드되지 않은 경우 애플리케이션 정정을 시도하여 클래스 로드 여부를 확인하십시오. 클래스가 올바른 권한을 가진 클래스 경로에 있고 다른 팩토리 클래스로 대체되지 않는 경우 클래스를 로드하는 데 사용된 API를 검사하십시오.
- 검색 페이지에 액세스하십시오. 을 클릭하여 클래스 로더
- 검색 유형으로는 클래스/패키지를 선택하십시오.
- 검색 용어에는 클래스 이름을 입력하십시오.
- 확인을 클릭하십시오. 클래스 이름별 검색 페이지가 표시되어 클래스를 로드하는 모든 클래스 로더가 나열됩니다.
- 페이지를 검사하여 클래스가 목록에 있는지 확인하십시오.
- 클래스가 목록에 있는데 ClassNotFound 예외가 발생한 경우
.jar 파일 또는 클래스가 올바른 컨텍스트에 없거나 현재
컨텍스트에서 잘못된 API 호출을 사용한 경우입니다. 클래스가 목록에 없는 경우 검색 페이지로 돌아가 다음을 수행하십시오.
- 예외를 생성한 클래스(Class.forName을 호출하는 클래스)를 검색하십시오.
- 클래스를 로드하는 클래스 로더를 확인하십시오.
- 클래스 로더의 클래스 경로를 평가하여 클래스 로더에 액세스 권한이 있거나 찾을 수 없는 클래스를 로드할 수 있는지 여부를 판별하십시오.
- 종속 클래스가 표시되지 않습니다.
- clsldr 클래스 로더가 cls 클래스를 로드하면 JVM(Java Virtual
Machine)은 clsldr을 호출하여 cls가 의존하는 클래스를 로드합니다.
종속 클래스는 clsldr의 논리 클래스 경로에서 볼 수 있어야 합니다. 그렇지
않으면 예외가 발생합니다. 사용자가 WebSphere Application Server 클래스가
JVM에 표시되도록 작성하거나 애플리케이션 클래스가 JVM 또는 WebSphere
확장 클래스 로더에 표시되도록 작성한 경우 이 조건이 일반적으로 발생합니다. 예를 들어 다음과 같습니다.
- 클래스 A가 클래스 B에 종속됩니다.
- 클래스 A가 WebSphere 확장 클래스 로더에 표시됩니다.
- 클래스 B는 WebSphere 확장자 클래스 로더 클래스 경로가 아닌 WAR 모듈 클래스 로더의 로컬 클래스 경로에 보여집니다.
JVM이 WebSphere 확장자 클래스 로더를 사용하여 클래스 A를 로드하면 같은 클래스 로더를 사용하여 클래스 B를 로드하려고 하며 결국에는 클래스를 찾을 수 없음 예외를 작성합니다.
이러한 문제점을 정정하려면 다음을 수행하십시오.
- 애플리케이션 특정 클래스가 적합한 애플리케이션 클래스 로더에 보여지도록 하십시오.
- 찾을 수 없는 클래스(클래스 B)를 검색하십시오.
- 클래스 B가 올바른 위치에 있는 경우 클래스 로더 뷰어에서 종속 클래스(클래스 A)를 로드하는 클래스를 검색하십시오.
- 클래스가 로드되지만 ClassNotFound 예외가 발생한 경우 .jar
파일 또는 클래스가 올바른 컨텍스트에 없거나 현재 컨텍스트에서 잘못된 API
호출을 사용한 경우입니다. 클래스가 없으면 다음을 수행하십시오.
- 예외를 생성한 클래스(Class.forName을 호출하는 클래스)를 검색하십시오.
- 클래스를 로드하는 클래스 로더를 확인하십시오.
- 클래스 로더의 클래스 경로를 평가하여 클래스 로더에 액세스 권한이 있거나 찾을 수 없는 클래스를 로드할 수 있는지 여부를 판별하십시오.
- JVM 또는 WebSphere 확장 클래스 로더에 호출자 클래스(클래스 B)가 표시되는지 확인하십시오.
NoClassDefFoundException
다음과 같은 경우 클래스 정의를 찾을 수 없음 예외가 발생하며 이 예외는 다음 조치로 정정할 수 있습니다.
- 클래스가 논리 클래스 경로에 없습니다.
- 자세한 정보는 ClassNotFoundException의 내용을 참조하십시오.
- 클래스를 로드할 수 없습니다.
- 클래스를 로드할 수 없는 이유는 다양합니다. 예를 들어, 종속 클래스를 로드하는 데 실패했거나 종속 클래스의 형식이 잘못되었거나 클래스의 버전 번호 때문입니다.
UnsatisfiedLinkError
다음과 같은 경우 연계 오류가 발생하며 이 예외는 다음 조치로 정정할 수 있습니다.
- 사용자 조치로 오류가 발생했습니다.
System.mapLibraryName이 잘못된 라이브러리 파일을 리턴합니다.
- 기본 라이브러리가 이미 로드되었습니다.
- 종속 기본 라이브러리를 사용했습니다.
- 사용자 조치로 오류가 발생했습니다.
몇몇 사용자 조치로 인해 다음과 같은 연계 오류가 발생할 수 있습니다.
- 라이브러리 확장자 이름이 플랫폼에 유효하지 않습니다.
라이브러리의 동적 링크 라이브러리 이름이 library_name.dll입니다.
라이브러리 이름이 library_name.so 또는 library_name.a입니다.
- System.loadLibrary가 잘못된 매개변수를 전달했습니다.
Name.dll 동적 링크 라이브러리를 로드하려면 Name을 loadLibrary 호출로 전달해야 합니다.
libName을 로드 라이브러리로 전달하면 libName.so 또는 libName.a 라이브러리가 로드됩니다.
- 라이브러리가 표시되지 않습니다.
- JVM 클래스 로더를 사용하여 기본 라이브러리를 찾거나 로드하는 것이 우수 사례입니다.
WebSphere Application Server는 시작 시 Java 라이브러리
경로(java.library.path)를 인쇄합니다. JVM 클래스 로더가 라이브러리를 로드하려는 경우 기본 라이브러리 파일을 포함하는
경로가 Java 라이브러리 경로에 있는지 확인하십시오.
이 경로에 있지 않은 경우 플랫폼 특정 기본 라이브러리 환경 변수 또는 서버 프로세스 정의의
java.library.path 시스템 특성에 경로를 추가하십시오.
일반적으로, JVM(Java Virtual Machine)은 xxx 클래스 로더에 대해 findLibrary()를 호출하여 System.loadLibrary()를 호출하는 클래스를 로드합니다. xxx.findLibrary()가 실패하면 JVM(Java Virtual Machine)이 JVM 클래스 로더를 사용하여 라이브러리를 찾으려고 시도하고 이 로더는 JVM 라이브러리 경로를 검색합니다. 라이브러리를 찾을 수 없는 경우 JVM(Java Virtual Machine)에 UnsatisfiedLinkError 예외를 작성합니다.
따라서 WebSphere 클래스 로더가 기본 라이브러리 myNativeLib를 찾도록 의도된 경우 라이브러리는 System.loadLibrary(myNativeLib)를 호출하는 클래스를 로드하는 클래스 로더의 nativelibpath에서 볼 수 있어야 합니다. 이는 다음 상황에서 필요하거나 바람직합니다.
데이터 소스 제공자의 기본 라이브러리가 WebSphere 확장 클래스 로더의 nativelibpath에서 볼 수 있어야 합니다. 이 경우 데이터 소스 제공자 구성의 기본 라이브러리 경로 설정에 기본 라이브러리를 포함하는 경로를 추가하십시오.
- 공유 라이브러리가 구성에 기본 라이브러리 경로를 가집니다. 공유 라이브러리는 애플리케이션 특정 라이브러리의 버전화를 사용 가능하게 하므로 공유 라이브러리 구성의 공유 라이브러리 코드에서 사용하는 기본 라이브러리에 경로를 지정하는 것을 고려하십시오.
올바른 WebSphere 클래스 로더가 System.loadLibrary()를 호출하는 클래스를 로드하며 기본 라이브러리 경로 설정에 기본 라이브러리가 표시되는지 확인하십시오.
![[AIX HP-UX Solaris]](../images/unix.gif)
- System.mapLibraryName이 잘못된 라이브러리 파일을 리턴합니다.
- 공유 라이브러리를 로드할 때 JVM이 mapLibraryName(libName)을 호출하여 libName을 플랫폼 특정 이름으로 변환합니다. AIX®, HP-UX 또는 Solaris 운영 체제에서 이 호출은 올바르지 않은 확장자(예: libName.a가 아닌 libName.so)를 가진 파일 이름을 리턴할 수 있습니다. 이러한 현상을 디버그하려면 System.mapLibraryName()을 호출하는 프로그램을 작성하고 올바른 파일 이름을 리턴하는지 확인하십시오.
- 기본 라이브러리가 이미 로드되었습니다.
- 이 경우 다음과 같은 오류로 인한 문제일 수 있습니다.
- 사용자 오류
- System.loadLibrary에 대한 다중 호출을 검사하여 불필요한 호출을 제거하십시오.
- 애플리케이션 다시 시작 오류
- JVM에는 한 번에 하나의 클래스 로더만 기본 라이브러리를 로드할 수 있는
제한사항이 있습니다. 가비지 콜렉터가 중지된 애플리케이션에서 클래스 로더를
정리하기 전에 애플리케이션을 다시 시작하면 오류가 발생합니다.
기본 라이브러리를 로드하는 클래스가 이동하는 경우 해당 기본 라이브러리
및 종속성에 따라 다른 모든 클래스도 이동해야 합니다.
이 조건을 정정하려면 기본 라이브러리의 로딩을 다시 로드하지 않는 클래스 로더로 이동하십시오.
- 기본 라이브러리를 로드하거나 기본 메소드가 있는 모든 애플리케이션 클래스를 찾으십시오.
- 1단계의 클래스에 종속되는 클래스(예: 로깅 패키지)를 식별하십시오.
- 서버 연관 공유 라이브러리 또는 분리된 공유 라이브러리를 작성하십시오.
- 1과 2단계에서 클래스에 로드된 애플리케이션의 JAR 파일을 3단계에서 작성된 공유 라이브러리로 이동하십시오.
- 변경사항을 저장하십시오.
- 애플리케이션을 다시 배치하고 시나리오를 다시 실행하십시오.
서버 범위 라이브러리의 클래스는 각 서버 라이프사이클에 대해 한 번 로드되므로 애플리케이션에서 필요한 기본 라이브러리는 애플리케이션의 라이프사이클에 관계없이 각 JVM(Java Virtual Machine)에 대해 한 번만 로드됩니다.
- 종속 기본 라이브러리를 사용했습니다.
- 종속 기본 라이브러리는 JVM 클래스 로더가 찾거나 로드해야 합니다.
즉, 기본 라이브러리(NL)가 다른 종속 라이브러리(DNL)에 종속되는
경우 JVM 클래스 로더는 Java 라이브러리 경로에서 DNL을 찾아야 합니다. 이는
JVM이 NL을 로드할 때 기본 코드를 실행하기 때문입니다.
DNL 종속관계를 발견하면 JVM 기본 코드가 JVM 클래스 로더만을
호출하여 해당 종속 관계를 해석할 수 있습니다. WebSphere 클래스 로더는 종속
기본 라이브러리를 로드할 수 없습니다.
분석되지 않은 기본 라이브러리가 들어 있는 경로를 포함하도록 Java 라이브러리 경로(LIBPATH)를 정의하는 플랫폼 특정 환경 변수를 수정하십시오.