[java] java.lang.NoClassDefFoundError : 클래스 XXX를 초기화 할 수 없습니다

public class PropHolder {
  public static Properties prop;

  static {
    //code for loading properties from file
  }
}

// Referencing the class somewhere else:
Properties prop = PropHolder.prop;

class PropHolder내 자신의 클래스입니다. 클래스는 기본 클래스와 동일한 JAR 파일에 있습니다. 따라서 클래스 경로에서 JAR이 누락되어서는 안됩니다.

로 JAR 파일을 살펴보면 나열된 파일을 jar tf myjarfile볼 수 있습니다 PropHolder.class.

Btw : 코드가 로컬 컴퓨터에서 제대로 실행되고 있습니다. 그러나 일부 스크립트를 사용하여 Linux 서버에 배포하면 작동하지 않았습니다. 따라서 코드의 문제가 아니라고 생각합니다. 그러나 어떤 이유로 든. 배포 프로세스는 추적하기가 매우 어렵습니다.

무엇이 문제 일 수 있습니까?



답변

최선의 방법은 여기에 문제가 있다는 것입니다.

static {
    //code for loading properties from file
}

잡히지 않은 예외가 발생하여 클래스를로드하려고 시도하는 실제 ClassLoader까지 전파 된 것처럼 보입니다. 그래도이를 확인하려면 스택 추적이 필요합니다.

PropHolder.prop정적 변수를 만들 때 또는 발생했습니다 .


답변

당신은 java.lang.NoClassDefFoundError클래스가 누락되었다는 것을 의미하지는 않습니다 (이 경우에는을 얻습니다 java.lang.ClassNotFoundException). 클래스를 읽으려고 할 때 클래스 정의를 읽는 중에 클래스 로더에 오류가 발생했습니다.

정적 이니셜 라이저 안에 try / catch를 넣고 예외를 살펴보십시오. 일부 파일을 읽고 로컬 환경과 다른 경우 문제의 원인 일 수 있습니다 (파일을 찾을 수 없거나 권한이없는 것일 수 있음).


답변

NoClassDefFoundError는 정적 블록 내부에서 무엇이 잘못되었는지에 대한 단서를 제공하지 않습니다. 정적 {…} 초기화 코드 안에 항상 이와 같은 블록을 두는 것이 좋습니다.

static {
  try {

    ... your init code here

  } catch (Throwable t) {
    LOG.error("Failure during static initialization", t);
    throw t;
  }
}


답변

나는 같은 예외가 있었는데, 이것이 내가 문제를 해결 한 방법입니다.

전제 조건 :

  1. 다른 클래스를 확장 한 Junit 클래스 (및 테스트)

  2. ApplicationContext는 프로젝트를 초기화하는 스프링을 사용하여 초기화되었습니다.

  3. @Before 메소드에서 애플리케이션 컨텍스트가 초기화되었습니다.

해결책:

부모 클래스에도 응용 프로그램 컨텍스트 내에서 초기화 된 일부 클래스가 필요했기 때문에 @BeforeClass 메서드에서 응용 프로그램 컨텍스트를 초기화하십시오.

이것이 도움이되기를 바랍니다.


답변

위에서 언급했듯이 이것은 여러 가지 일 수 있습니다. 제 경우에는 속성 파일에서 누락 된 항목에 의존하는 정적으로 초기화 된 변수가있었습니다. 속성 파일에 누락 된 항목을 추가하면 문제가 해결되었습니다.


답변

며칠 전, 나는 당신과 같은 질문을 만났습니다. 모든 코드는 로컬 컴퓨터에서 제대로 실행되지만 오류 (noclassdeffound & initialize)가 나타납니다. 그래서 솔루션을 게시했지만 이유를 모르겠습니다. 단지 가능성을 높입니다. 누군가 John이 도움을 줄 수 있기를 바랍니다. @ John Vint 먼저, 나는 당신에게 내 문제를 보여줄 것입니다. 내 코드에는 정적 변수와 정적 블록이 있습니다. 이 문제를 처음 만났을 때 John Vint의 솔루션을 시도하고 예외를 잡으려고했습니다. 그러나 나는 아무것도 잡지 못했다. 그래서 정적 변수 (그러나 지금은 그것들이 같은 것을 알고 있기 때문에)라고 생각했지만 여전히 아무것도 찾지 못했습니다. 그래서 나는 리눅스 컴퓨터와 내 컴퓨터의 차이점을 찾으려고 노력합니다. 그런 다음이 문제는 한 프로세스에서 여러 스레드가 실행될 때만 발생한다는 것을 알았습니다 (그런데 리눅스 머신에는 더블 코어와 더블 프로세스가 있습니다). 즉, 동일한 프로세스에서 실행되는 두 가지 작업 (정적 블록 또는 변수가있는 코드를 사용하는 코드)이 있으면 잘못되지만 다른 프로세스에서 실행되면 둘 다 정상입니다. 리눅스 머신에서는

mvn -U clean  test -Dtest=path 

작업을 실행하려면 정적 변수가 컨테이너를 시작하거나 새 클래스 로더를 초기화하는 것이므로 jvm이 중지 될 때까지 유지되고 한 프로세스의 모든 작업이 중지 될 때만 jvm이 중지됩니다. 모든 작업은 새로운 컨테이너 (또는 클래스 로더)를 시작하고 jvm을 혼란스럽게 만듭니다. 결과적으로 오류가 발생합니다. 어떻게 해결해야합니까? 내 솔루션은 maven 명령에 새 명령을 추가하고 모든 작업을 동일한 컨테이너로 이동시키는 것입니다.

-Dxxx.version=xxxxx #sorry can't post more

이 문제를 이미 해결했을 수도 있지만 같은 문제를 해결하는 다른 사람들에게 도움이되기를 바랍니다.


답변

같은 예외가 있었지만 디버그 모드에서 실행하는 동안에 만 문제가 해결되었습니다 (3 일 후). build.gradle에서 : “multiDexEnabled true”가 defaultConfig 섹션에 설정되었습니다.

        defaultConfig {
    applicationId "com.xxx.yyy"
    minSdkVersion 15
    targetSdkVersion 28
    versionCode 5123
    versionName "5123"
    // Enabling multidex support.
    multiDexEnabled true
}

그러나 이것으로는 충분하지 않았습니다. 하지만 내가 바뀌었을 때 :

public class MyAppClass  extends Application 

에:

public class MyAppClass  extends MultiDexApplication 

이것은 그것을 해결했다. 이것이 누군가를 도울 수 있기를 바랍니다.