IT이야기

Java에서 NoClassDefoundError를 받는 이유

cyworld 2022. 5. 6. 19:48
반응형

Java에서 NoClassDefoundError를 받는 이유

나는 a를 얻고 있다.NoClassDefFoundErrorJava 응용프로그램을 실행할 때.일반적으로 이것의 원인은 무엇인가?

이것이 컴파일 시간과 런타임 간의 클래스 경로 불일치 때문일 수 있지만, 반드시 사실인 것은 아니다.

이 경우에는 두세 가지 다른 예외를 우리 머릿속에 똑바로 두는 것이 중요하다.

  1. java.lang.ClassNotFoundException 이 예외는 클래스가 클래스 경로에서 발견되지 않았음을 나타낸다.이것은 우리가 클래스 정의를 로드하려고 했고, 클래스가 클래스 경로에 존재하지 않았음을 나타낸다.

  2. java.lang.NoClassDefFoundError 이 예외는 JVM이 클래스의 정의를 위해 내부 클래스 정의 데이터 구조를 조사했지만 찾지 못했음을 나타낸다.이것은 클래스 경로에서 로드할 수 없다고 말하는 것과 다르다.보통 이것은 우리가 이전에 클래스를 클래스 경로에서 로드하려고 시도했지만 실패했다는 것을 나타낸다. - 지금은 클래스를 다시 사용하려고 하지만(그래서 지난번에 실패했으므로 로드해야 함), 더 일찍 로딩하지 못했기 때문에(그리고 합리적으로 다시 실패할 것으로 의심함) 로딩하려고 시도조차 하지 않을 것이다.이전 실패는 ClassNotFoundException 또는 예외일 수 있음InInInitializerError(정적 초기화 블록의 오류를 나타냄) 또는 기타 여러 가지 문제요점은 NoClassDefoundError가 반드시 클래스 경로 문제는 아니라는 것이다.

이는 코드가 종속된 클래스 파일이 있고 컴파일 시간에 존재하지만 런타임에는 찾을 수 없는 경우에 발생한다.빌드 시간과 런타임 클래스 경로의 차이점을 찾아보십시오.

여기에 설명해야 할 코드가 있다.java.lang.NoClassDefFoundError자세한 설명은 제러드의 답변을 참고하십시오.

NoClassDefoundErrorDemo.java

public class NoClassDefFoundErrorDemo {
    public static void main(String[] args) {
        try {
            // The following line would throw ExceptionInInitializerError
            SimpleCalculator calculator1 = new SimpleCalculator();
        } catch (Throwable t) {
            System.out.println(t);
        }
        // The following line would cause NoClassDefFoundError
        SimpleCalculator calculator2 = new SimpleCalculator();
    }

}

SimpleCalculator.java

public class SimpleCalculator {
    static int undefined = 1 / 0;
}

자바에서 NoClassDefoundError

정의:

  1. Java Virtual Machine은 컴파일 시간에 사용 가능했던 특정 클래스를 런타임에 찾을 수 없다.

  2. 컴파일 시간 동안 클래스가 존재했지만 런타임 동안 Java 클래스 경로에서 사용할 수 없는 경우.

여기에 이미지 설명을 입력하십시오.

예:

  1. 클래스는 Classpath에 있지 않으며, 그것을 알 수 있는 확실한 방법은 없지만 System.getproperty("java.classpath")를 인쇄할 수 있으며, 거기서 실제 런타임 클래스 경로를 최소한 알 수 있다.
  2. NoClassDefoundError의 간단한 예는 클래스가 누락된 JAR 파일에 속하거나 JAR이 클래스 경로에 추가되지 않았거나 때때로 내 동료 중 한 명이 tibco.jar를 tibco_v3.jar로 변경했고 프로그램이 java.lang으로 실패하는 경우 등이다.NoClassDefoundError와 나는 무엇이 문제인지 궁금했다.

  3. 당신이 생각하는 클래스 경로와 함께 명시적으로 -classpath 옵션으로 실행해 보십시오. 만약 그것이 작동한다면 누군가가 Java 클래스 경로를 재정의하고 있다는 것은 분명 짧은 신호 입니다.

  4. JAR 파일에 대한 권한 문제로 인해 Java에서 NoClassDefoundError도 발생할 수 있다.
  5. XML 구성에 대한 오타가 Java에서 NoClassDefoundError를 발생시킬 수도 있다.
  6. 패키지에 정의된 컴파일된 클래스가 JApplt와 같이 로드되는 동안 동일한 패키지에 표시되지 않을 경우 Java에서 NoClassDefoundError를 발생시킨다.

가능한 해결책:

  1. Java Classpath에서는 클래스를 사용할 수 없다.
  2. J2EE 환경에서 작업하는 경우 다중 Classloader 중 Class의 가시성 또한 java.lang을 유발할 수 있다.NoClassDefoundError에 대한 자세한 내용은 예제 및 시나리오 섹션을 참조하십시오.
  3. java.lang을 확인하십시오.예외로그 파일의 InInInitializerError.정적 초기화 오류로 인한 NoClassDefoundError는 매우 일반적이다.
  4. 왜냐하면 NoClassDefoundError는 java.lang의 하위 클래스이기 때문이다.링크원본 라이브러리와 같은 종속성 중 하나를 사용할 수 없는 경우에도 발생할 수 있다.
  5. 모든 시작 스크립트가 Classpath 환경 변수를 재정의하고 있음.
  6. jar 명령을 사용하여 프로그램을 실행하고 있을 수 있으며 매니페스트 파일의 ClassPath 속성에 클래스가 정의되어 있지 않은 경우.

리소스:

NoClassDefoundError를 해결하는 3가지 방법

자바.의NoClassDefoundError 문제 패턴

나는 때때로 런타임에 발견되는 클래스의 호환되지 않는 버전으로 코드를 컴파일할 때 NoClassDefound 오류가 발생한다는 것을 발견했다.내가 기억하는 특정 인스턴스는 아파치 축 라이브러리에 있다.내 런타임 클래스 경로에 실제로 2개의 버전이 있었는데, 올바른 버전이 아닌 오래된 버전과 호환되지 않는 버전을 선택해서 NoClassDefound 오류가 발생했다.이것은 내가 이와 유사한 명령을 사용하고 있는 명령줄 앱에 있었다.

set classpath=%classpath%;axis.jar

다음을 사용하여 적절한 버전을 픽업할 수 있었다.

set classpath=axis.jar;%classpath%;

이것이 내가 지금까지 찾은 최선의 해결책이다.

만약 우리가 소포라고 불리는 것을 가지고 있다고 가정하자.org.mypackage클래스 포함:

  • 헬로월드(메인클래스)
  • 서포트클래스
  • UtilClass

이 패키지를 정의하는 파일은 실제로 디렉터리에 저장되며D:\myprogram (Windows에서)/home/user/myprogram(Linux에서).

파일 구조는 다음과 같을 것이다.

Java를 호출할 때 실행할 응용 프로그램의 이름을 지정하십시오.org.mypackage.HelloWorld그러나 우리는 또한 Java에게 우리의 패키지를 정의하는 파일들과 디렉토리들을 어디에서 찾아야 하는지 알려야 한다.그래서 프로그램을 시작하려면 다음 명령을 사용해야 한다.

당신이 많은 것을 볼 수 있는 흥미로운 사례NoClassDefFoundErrors다음과 같은 경우:

  1. throw a RuntimeException에서static너의 반에서 한 블록.Example
  2. 가로채기(또는 테스트 케이스에 던져진 것처럼 문제가 되지 않는 경우)
  3. 이 클래스의 인스턴스 만들기 시도Example

static class Example {
    static {
        thisThrowsRuntimeException();
    }
}

static class OuterClazz {

    OuterClazz() {
        try {
            new Example();
        } catch (Throwable ignored) { //simulating catching RuntimeException from static block
            // DO NOT DO THIS IN PRODUCTION CODE, THIS IS JUST AN EXAMPLE in StackOverflow
        }

        new Example(); //this throws NoClassDefFoundError
    }
}

NoClassDefError을 동반하여 던질 것이다.ExceptionInInitializerError정전기로부터RuntimeException.


이것은 특히 당신이 볼 때 중요한 경우다.NoClassDefFoundErrors너희 부대 시험에서 말이야

어떻게 보면 '나눔'을 하고 있는 것이다.static 스 스 차단(초기)ExceptionInInitializerError단 하나의 테스트 케이스에 있을 것이다.문제가 있는 것을 사용하는 첫 번째 것.Example 클래스를 . 기타 테스트 사례:Example수업은 그냥 던져버릴 것이다.NoClassDefFoundErrors.

나는 메이븐과 함께 스프링 프레임워크를 사용하고 있었는데 내 프로젝트에서 이 오류를 해결했다.

수업 중에 런타임 오류가 있었다.나는 속성을 정수로 읽고 있었지만, 속성 파일에서 값을 읽었을 때 그 값은 두 배가 되었다.

스프링은 나에게 런타임이 실패한 라인의 전체 스택 추적을 주지 않았다.그것은 간단히 말했다.NoClassDefFoundError. 그러나 내가 그것을 네이티브 자바 어플리케이션으로 실행했을 때 (MVC에서 꺼내기) 그것은ExceptionInInitializerError그게 진짜 원인이고 내가 오류를 추적한 방법이야

@xli의 대답은 내게 내 코드에 무엇이 잘못되었을지 통찰해 주었다.

런타임 클래스 로더가 로드한 클래스가 자바 루트로드러가 이미 로드한 클래스에 액세스할 수 없는 경우 NoClassFoundError를 얻는다.서로 다른 클래스 로더가 서로 다른 보안 도메인에 있기 때문에(자바에 따라) jvm은 rootloader에 의해 이미 로드된 클래스가 런타임 로더 주소 공간에서 확인되는 것을 허용하지 않는다.

'java -java에이전트:tracer.jar [YOUR Java ARGS]'로 프로그램을 실행하십시오.

로딩된 클래스를 보여주는 출력을 생성하며, 로더가 클래스를 로드한 환경을 생성한다.왜 수업이 해결되지 않는지 추적하는 것은 매우 도움이 된다.

// ClassLoaderTracer.java
// From: https://blogs.oracle.com/sundararajan/entry/tracing_class_loading_1_5

import java.lang.instrument.*;
import java.security.*;

// manifest.mf
// Premain-Class: ClassLoadTracer

// jar -cvfm tracer.jar manifest.mf ClassLoaderTracer.class

// java -javaagent:tracer.jar  [...]

public class ClassLoadTracer 
{
    public static void premain(String agentArgs, Instrumentation inst) 
    {
        final java.io.PrintStream out = System.out;
        inst.addTransformer(new ClassFileTransformer() {
            public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {

                String pd = (null == protectionDomain) ? "null" : protectionDomain.getCodeSource().toString();
                out.println(className + " loaded by " + loader + " at " + new java.util.Date() + " in " + pd);

                // dump stack trace of the thread loading class 
                Thread.dumpStack();

                // we just want the original .class bytes to be loaded!
                // we are not instrumenting it...
                return null;
            }
        });
    }
}

아래 기술은 여러 번 나를 도왔다.

System.out.println(TheNoDefFoundClass.class.getProtectionDomain().getCodeSource().getLocation());

여기서 TheNoDefoundClass는 프로그램이 사용하는 동일한 라이브러리의 이전 버전을 선호하기 때문에 "잃어버릴" 수 있는 클래스다.이것은 가장 빈번하게 일어나는 경우로, 클라이언트 소프트웨어가 지배적인 용기에 배치될 때, 그것의 자체적인 클래스 로더와 가장 인기 있는 리브의 수 톤의 고대 버전들로 무장되어 있다.

코드(EMF 등)를 생성한 경우 모든 스택 공간을 사용하는 정적 이니시에이터가 너무 많을 수 있다.

스택 오버플로 질문 Java 스택 크기를 늘리는 방법을 참조하십시오.

ClassNotFoundException 대 NoClassDefoundError

[ClassLoader]

정적 및 동적 클래스 로드

Static(Implicit) class loading의 결과 참조, 인맥은 스의 결과이다.

MyClass myClass = new MyClass();

Dynamic(Explicit) class loading forName(), loadClass(), findSystemClass() 결과의

MyClass myClass = (MyClass) Class.forName("MyClass").newInstance();

모든 학급에는 a가 있다.ClassLoader어떤 것을 사용하는지loadClass(String name);그게 이유다

explicit class loader uses implicit class loader

NoClassDefFoundError의 일부분이다explicit class loader. 이다Error컴파일 중에 이 클래스가 제시되었지만 현재(실행 시간 내에) 결석했다는 것을 보증하기 위해.

ClassNotFoundException의 일부분이다implicit class loader. 이다Exception추가적으로 사용할 수 있는 시나리오(예: 반사)로 탄력적이다.

동일한 프로젝트의 서로 다른 체크아웃 복사본 2개

나의 경우, 문제는 이클립스가 동일한 프로젝트의 서로 다른 두 부본을 구별할 수 없다는 것이었다.한 개는 트렁크(SVN 버전 제어)에 잠겨 있고 다른 한 개는 한 번에 한 지점에서 작동하고 있다.나는 JUnit 테스트 사례로 작업 복사본의 한 가지 변경을 시도했는데, 여기에는 개인 내부 클래스를 스스로 공용 클래스로 추출하는 내용이 포함되어 있고, 작업하는 동안 변경이 필요한 코드의 다른 부분을 둘러보기 위해 프로젝트의 다른 복사본을 열어본다.어느 틈엔가 더NoClassDefFoundError개인 내부 계층이 없다고 불평하면서 불쑥 나타났다; 스택 추적을 두 번 클릭하면 잘못된 프로젝트 복사본의 소스 파일로 오게 되었다.

프로젝트의 트렁크 카피를 닫고 테스트 케이스를 다시 실행한 것이 문제를 없앴다.

모든 모듈에 대해 PreDexLibrary를 사용하지 않도록 설정하여 문제를 해결함:

dexOptions {
        preDexLibraries false
        ...

프로젝트에 다른 모듈의 Maven 종속성을 추가했을 때 이 오류가 발생했는데, 결국 추가로 문제가 해결되었다.-Xss2m내 프로그램의 JVM 옵션(JDK5.0 이후 기본적으로 1MB).그 프로그램은 클래스를 로드하기에 충분한 스택을 가지고 있지 않다고 여겨진다.

NoClassDefFoundError정적 이니셜라이저가 런타임에 사용할 수 없는 리소스 번들을 로드하려고 할 때도 발생할 수 있음(예: 영향을 받는 클래스가 에서 로드하려고 하는 속성 파일)META-INF디렉토리, 그러나 거기에 없다. 면으라면NoClassDefFoundError, 때때로 당신은 전체 스택 추적을 볼 수 없을 것이다; 이것을 극복하기 위해 당신은 일시적으로 를 사용할 수 있다.catch에 대한 조항.Throwable:

try {
    // Statement(s) that cause(s) the affected class to be loaded
} catch (Throwable t) {
    Logger.getLogger("<logger-name>").info("Loading my class went wrong", t);
}

Tomcat/J에 애플리케이션을 배포하는 동안 NoClassDefoundError가 발생함BOSS 서버.나는 그 문제를 해결하기 위해 서로 다른 의존성을 가지고 놀았지만, 계속 같은 실수를 했다.모든 자바를 표시했다.* pom.xml에 제공된 의존성, 그리고 전쟁은 문자 그대로 의존성이 없었다.그래도 그 문제는 계속 불거져 나왔다.

마침내 src/main/webapp/WEB-INF/classes에는 내 전쟁에 복사되는 클래스 폴더가 있다는 것을 알게 되었고, 그래서 컴파일된 클래스 대신 이 클래스가 복사되고 있었으므로, 이 문제를 해결하는 종속성 변화는 없었다.

따라서 이전에 컴파일된 데이터가 복사되는 경우, 클래스 폴더와 새로 컴파일한 후 효과가 나타났다!

만약 누군가가 이 곳에 온다면java.lang.NoClassDefFoundError: org/apache/log4j/Logger에러, 나의 경우 log4j 2를 사용했기 때문에 생성되었으며(그러나 나는 여기에 함께 제공되는 모든 파일을 추가하지 않았다), 일부 종속성 라이브러리는 log4j 1을 사용했다.해결책은 Log4j 1.x 브리지: 항아리를 추가하는 것이었다.log4j-1.2-api-<version>.jar로그4j 2와 함께 제공된다.log4j 2 마이그레이션에 대한 추가 정보

이 오류는 확인되지 않은 Java 버전 요구 사항으로 인해 발생할 수 있다.

나의 경우 SDKMAN!을 사용하여 Java 9에서 Java 8로 전환하여, 높은 인지도의 오픈 소스 프로젝트를 구축하면서 이 오류를 해결할 수 있었다.

sdk list java
sdk install java 8u152-zulu
sdk use java 8u152-zulu

그런 다음 아래 설명된 대로 새로 설치하십시오.


Maven을 빌드 도구로 사용할 때, 테스트가 비활성화된 상태에서 깨끗한 '설치' 빌드를 수행하는 것이 때로는 도움이 되고, 대개는 만족스럽다.

mvn clean install -DskipTests

이제 모든 것이 지어지고 설치되었으니, 먼저 가서 테스트를 진행해도 된다.

mvn test

프로젝트의 Java 빌드 경로에 있는 "주문 및 내보내기" 탭에서 클래스를 내보내지 않았을 때 NoClassDefound 오류가 발생함프로젝트의 빌드 경로에 추가하는 종속성의 "주문 및 내보내기" 탭에 체크 표시를 하십시오.Eclipse 경고: XXXXXXXXX.jar는 내보내거나 게시되지 않음을 참조하십시오. Runtime ClassNotFoundExceptions가 발생할 수 있다.

또한 특정 패키지 이름을 가진 IDE에서 코드 파일을 복사하고 터미널을 사용하여 실행하려고 하기 때문일 수 있다.먼저 코드에서 패키지 이름을 제거해야 할 것이다.이런 일은 내게도 일어난다.

나의 경우 JDK 버전이 일치하지 않아서 이 오류가 발생했어.Intellij에서 애플리케이션을 실행하려고 했을 때는 작동하지 않았지만 명령줄에서 실행하면 작동했다.Intellij가 설정한 Java 11 JDK로 실행을 시도하고 있었지만, 명령줄에서 Java 8 JDK로 실행하고 있었기 때문이다. File > Project Structure > Project Settings > Project SDK에서 그 설정을 전환한 후, 나에게 효과가 있었다.

여기서 모든 사람들이 Java 구성 문제, JVM 문제 등에 대해 이야기하는데, 나의 경우 오류는 이러한 주제와 전혀 관련되지 않았으며 매우 사소한 이성을 쉽게 해결할 수 있었다.컨트롤러(Spring Boot 애플리케이션)의 끝점에서 주석을 잘못 달았었습니다.

JavaE에서 Liberty 서버와 함께 작업하는 NoClassDefoundError와 관련하여 흥미로운 문제가 있었다.IMS 리소스 어댑터를 사용하고 있었는데 server.xml에 이미 imsudbJXA.rar용 리소스 어댑터가 있었다.imsudbXA.rar용 새 어댑터를 추가했을 때 DLIException, IMSConnectionSpec 또는 SQLInteractionSpec에 대한 인스턴스 개체에 대해 이 오류가 발생하기 시작함.이유는 알 수 없었지만 imsudbXA.rar만 사용하여 내 작업에 사용할 server.xml을 새로 만들어 해결했다.server.xml에서 여러 리소스 어댑터를 사용하는 것은 괜찮다고 확신하는데, 나는 그것을 조사할 시간이 없었다.

[https://www.infoq.com/articles/single-file-execution-java11/] 업데이트:

Java SE 11에서는 중간 컴파일 없이 단일 소스 코드 파일을 직접 실행할 수 있는 옵션이 제공된다.단지 당신의 편의를 위해서, 당신 같은 신참들이 자바 + 자바를 운영하지 않아도 되도록(물론, 그들은 그것이 왜 그런 것인지 혼란스럽게 남겨두게 된다.

나는 이런 오류가 있었지만 이 실에 근거해 해결책을 알아내지 못하고 스스로 해결했다.

내 문제로 나는 이 코드를 컴파일하고 있었다.

package valentines;

import java.math.BigInteger;
import java.util.ArrayList;

public class StudentSolver {
    public static ArrayList<Boolean> solve(ArrayList<ArrayList<BigInteger>> problems) {
        //DOING WORK HERE
        
    }
    public static void main(String[] args){
        //TESTING SOLVE FUNCTION
    }
    
}

는 이 . 하는 것은 잘하려고 노력했다: 그런다./ProjectName/valentinesput 폴loto 폴다. 컴파일 작업은 잘 되었지만 실행하려고 시도했다.java StudentSolver

NoClassDefError를 받았어.

이 문제를 해결하려면 다음을 제거하십시오.package valentines;

나는 자바 패키지 등에 그다지 정통하지는 않지만 이렇게 해서 내 오류를 고친 것은 다른 사람이 이미 답을 했는데 내 문제로 해석할 수 없다면 너무나 미안한 일이다.

Java는 런타임에 클래스 A를 찾을 수 없었다.클래스 A는 다른 작업공간에서 maven 프로젝트 ArtClient에 있었다.그래서 나는 ArtClient를 나의 Eclipse 프로젝트에 수입했다.내 프로젝트 중 두 가지는 ArtClient를 종속성으로 사용하는 것이었습니다.이러한 항목에 대한 프로젝트 참조로 라이브러리 참조를 변경했다(빌드 경로 -> 빌드 경로 구성).

그리고 문제는 사라졌다.

나도 같은 문제가 있었고, 여러 시간 동안 재고로 있었다.

해결책을 찾았어.나의 경우, 그것 때문에 정의된 정적인 방법이 있었다.JVM은 해당 클래스의 다른 개체를 만들 수 없다.

예를 들어,

private static HttpHost proxy = new HttpHost(proxyHost, Integer.valueOf(proxyPort), "http");

SRC 라이브러리에서 파일 두 개를 삭제한 후 이 메시지를 받았는데, 파일을 다시 가져왔을 때 이 오류 메시지가 계속 보였어.

내 해결책은: 이클립스를 다시 시작하라는 것이었다.그 이후로 나는 이 메시지를 다시 보지 못했다 :-)

이 항목이 다음에서 일치하는지 확인하십시오.module:app그리고module:lib:

android {
    compileSdkVersion 23
    buildToolsVersion '22.0.1'
    packagingOptions {
    }

    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 23
        versionCode 11
        versionName "2.1"
    }

참조URL: https://stackoverflow.com/questions/34413/why-am-i-getting-a-noclassdeffounderror-in-java

반응형