문제

크게 XML 기반 Java 응용 프로그램을 개발하여 최근 Ubuntu Linux에서 흥미로운 문제를 겪었습니다.

내 응용 프로그램, 사용 Java 플러그인 프레임 워크, 변환 할 수없는 것처럼 보입니다 dom4j-XML 문서를 만들었습니다 바틱 SVG 사양의 구현.

콘솔에서 오류가 발생한다는 것을 알게됩니다.

Exception in thread "AWT-EventQueue-0" java.lang.LinkageError: loader constraint violation in interface itable initialization: when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;" the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader) of the current class, org/apache/batik/dom/svg/SVGOMDocument, and the class loader (instance of <bootloader>) for interface org/w3c/dom/Document have different Class objects for the type org/w3c/dom/Attr used in the signature
    at org.apache.batik.dom.svg.SVGDOMImplementation.createDocument(SVGDOMImplementation.java:149)
    at org.dom4j.io.DOMWriter.createDomDocument(DOMWriter.java:361)
    at org.dom4j.io.DOMWriter.write(DOMWriter.java:138)

문제는 JVM의 원래 클래스 로더와 플러그인 프레임 워크에 의해 배치 된 클래스 로더 간의 충돌로 인해 발생한다고 생각합니다.

내가 아는 한, 프레임 워크를 사용할 수있는 클래스 로더를 지정할 수는 없습니다. 해킹 할 수는 있지만이 문제를 해결하는 데 덜 공격적인 접근 방식을 선호합니다. (어떤 이유로 든 Linux 시스템에서만 발생하기 때문입니다.

여러분 중 한 명이 그러한 문제를 겪었고 문제를 해결하거나 최소한 문제의 핵심에 도달하는 방법을 알고 있습니까?

도움이 되었습니까?

해결책

LinkageError는 클래스 C가 하나 이상의 클래스 로더로로드 된 클래스 C를 가지고 있으며 해당 클래스가 동일한 코드 (비교, 캐스트 등)에서 함께 사용되고있는 클래식 케이스에서 얻을 수있는 것입니다. 동일한 클래스 이름인지 또는 동일한 항아리에서로드 된 경우에도 중요하지 않습니다. 한 클래스 로더의 클래스는 다른 클래스 로더에서로드 된 경우 항상 다른 클래스로 취급됩니다.

메시지 (수년에 걸쳐 많이 개선 된 메시지)는 다음과 같이 말합니다.

Exception in thread "AWT-EventQueue-0" java.lang.LinkageError: 
loader constraint violation in interface itable initialization: 
when resolving method "org.apache.batik.dom.svg.SVGOMDocument.createAttribute(Ljava/lang/String;)Lorg/w3c/dom/Attr;" 
the class loader (instance of org/java/plugin/standard/StandardPluginClassLoader) 
of the current class, org/apache/batik/dom/svg/SVGOMDocument, 
and the class loader (instance of ) for interface org/w3c/dom/Document 
have different Class objects for the type org/w3c/dom/Attr used in the signature

따라서 여기서 문제는 svgomdocument.createattribute () 메소드를 해결하는 데있어서 org.w3c.dom.attr (표준 DOM 라이브러리의 일부)를 사용합니다. 그러나 Batik으로로드 된 attr의 버전은 다른 클래스 로더에서로드되었습니다.

Batik의 버전이 Java 플러그인에서로드 된 것 같습니다. 그리고 당신의 내장 JVM 로더 중 하나 일 가능성이 높은 "" "에서 귀하의로드되고 있습니다.

세 가지 저명한 클래스 로더 모델은 다음과 같습니다.

  • 위임 (JDK의 기본값 - 부모에게 물어보세요)
  • 사후 지연 (플러그인, 서블릿 및 고립을 원하는 장소 - 물어 보면 부모님)
  • 형제 자매 (OSGI, Eclipse 등과 같은 종속성 모델 공통)

JPF 클래스 로더가 어떤 위임 전략을 사용하는지는 모르겠지만, 핵심은 하나의 버전의 DOM 라이브러리를로드하고 모든 사람이 동일한 위치에서 해당 클래스를 공급하기를 원한다는 것입니다. 이는 클래스 경로에서 제거하고 플러그인으로로드하거나 Batik이로드하는 것을 방지하는 것을 의미 할 수 있습니다.

다른 팁

클래스 로더 계층 구조 문제처럼 들립니다. 애플리케이션이 어떤 유형의 환경에 배치되어 있는지 알 수 없지만 때로는이 문제가 웹 환경에서 발생할 수 있습니다. 여기서 응용 프로그램 서버가 클래스 로더의 계층 구조를 생성하는 다음과 같은 것과 비슷합니다.

Javahome/lib- 루트로
AppServer/Lib- 루트의 자녀로서
WebApp/Web -Inf/lib- 루트의 자녀의 자녀로서

일반적으로 클래스 로더는 부모 클래스 로더에로드를 위임합니다 (이것은로 알려져 있습니다.parent-first"), 그리고 해당 클래스 로더가 클래스를 찾을 수 없다면, 하위 클래스 로더가 시도합니다. 예를 들어, 클래스가 WebApp/Web-Inf/Lib에 항아리로 배포 된 경우 클래스를로드하려고 시도하면 먼저 다음에 해당하는 클래스 로더를 묻습니다. AppServer/Lib 클래스를로드하기 위해 (이를 통해 Javahome/Lib에 해당하는 클래스 로더에게 클래스를로드하도록 요청),이 조회가 실패하면 Web-Inf/Lib 가이 클래스와 일치하는 것을 검색합니다.

웹 환경에서는이 계층 구조에 문제가 발생할 수 있습니다. 예를 들어, 이전에 제가 실수 한 한 가지 실수/문제는 Web-Inf/Lib의 클래스가 AppServer/Lib에 배치 된 클래스에 의존했을 때 Web-Inf/Lib에 배포 된 클래스에 의존 할 때였습니다. 클래스 로더가 상위 클래스 로더에 위임 할 수 있지만 트리를 다시 위임 할 수 없기 때문에 실패가 발생했습니다. 따라서 Web-Inf/Lib 클래스 로더는 AppServer/Lib 클래스 로더에게 클래스를 요청하고 AppServer/Lib 클래스 로더는 해당 클래스를로드하고 종속 클래스를로드하려고 시도하고 AppServer/Lib 또는 Javahome에서 해당 클래스를 찾을 수 없기 때문에 실패합니다. /lib.

따라서 웹/앱 서버 환경에서 앱을 배포하지는 않지만 환경에 클래스 로더의 계층 구조가 설정되어 있으면 너무 긴 설명이 적용될 수 있습니다. 그것을합니까? JPF가 플러그인 기능을 구현하기 위해 일종의 클래스 로더 마법을 수행하고 있습니까?

이것이 나를 위해 꽤 잘 작동하기 때문에 누군가를 도울 것입니다. 자신의 종속성을 통합하여 문제를 해결할 수 있습니다. 이 간단한 단계를 따르십시오

먼저 다음과 같은 오류를 확인하십시오.

  • 메소드 실행 실패 :
  • java.lang.linkageerror : 로더 제약 조건 위반 :
  • 방법을 해결할 때 "org.slf4j.impl.staticLoggerBinder.getLoggerFactory () lorg/slf4j/iloggerFactory; "
  • 현재 클래스의 클래스 로더 (ORG/OPENMRS/MODULE/MODULECLASSLOADER의 인스턴스) ORG/SLF4J/loggerfactory,
  • 그리고 해결 된 클래스의 클래스 로더 (Org/Apache/Catalina/Loader/WebappClassLoader의 인스턴스), Org/Slf4J/impl/staticLoggerBinder,
  • taticloggerbinder.getLoggerFactory () lorg/slf4j/iloggerfactory 유형에 대한 다른 클래스 객체가 있습니다. 서명에 사용됩니다

  1. 강조 표시된 두 수업을 참조하십시오. "staticloggerbinder.class jar 다운로드"& "loggerafactory.class jar 다운로드"와 같은 Google 검색. 이것은 당신에게 먼저 또는 어떤 경우에는 두 번째 링크를 보여줄 것입니다 (사이트는 http://www.java2s.com ) 프로젝트에 포함 된 JAR 버전 중 하나입니다. 당신은 그것을 직접 현명하게 식별 할 수 있지만, 우리는 Google에 중독되어 있습니다.)

  2. 그 후 당신은 JAR 파일 이름을 알게 될 것입니다. 제 경우에는 slf4j-log4j12-1.5.6.jar & slf4j-api-1.5.8과 같습니다.

  3. 이제이 파일의 최신 버전은 여기에서 사용할 수 있습니다. http://mvnrepository.com/ (실제로 모든 버전은 지금까지 Maven이 의존성을 얻는 사이트입니다).
  4. 이제 최신 버전의 종속성으로 두 파일을 추가하십시오 (또는 선택한 버전은 모두 동일하게 유지). 다음은 pom.xml에 포함시켜야하는 종속성입니다.

<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.7</version>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-log4j12</artifactId>
    <version>1.7.7</version>
</dependency>

How to get dependecy definition from Maven Site

클래스 로더를 지정할 수 있습니까? 그렇지 않은 경우 컨텍스트 클래스 로더를 그렇게 지정하십시오.

Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
try {
    thread.setContextClassLoader(yourClassLoader);
    callDom4j();
} finally {
    thread.setContextClassLoader(contextClassLoader);
}

Java 플러그인 프레임 워크에 익숙하지는 않지만 Eclipse에 대한 코드를 작성하고 때때로 비슷한 문제가 발생합니다. 나는 그것이 그것을 고치겠다고 보장하지는 않지만 아마도 샷의 가치가있을 것입니다.

Alex와 Matt의 답변은 매우 도움이됩니다. 나는 그들의 분석도 혜택을받을 수 있습니다.

NetBeans RCP 프레임 워크에서 Batik 라이브러리를 사용할 때도 같은 문제가 있었으며 Batik 라이브러리는 "라이브러리 래퍼 모듈"으로 포함됩니다. 다른 모듈이 XML API를 사용하고 해당 모듈에 대해 BATIK에 대한 종속성이 필요하지 않은 경우 클래스 로더 제약 조건 위반 문제는 유사한 오류 메시지와 함께 발생합니다.

NetBeans에서 개별 모듈은 전용 클래스 로더를 사용하며 모듈 간의 종속성 관계는 적합한 클래스 로더 대표 라우팅을 의미합니다.

Batik 라이브러리 번들에서 XML-APIS JAR 파일을 생략하여 문제를 해결할 수 있습니다.

지정된대로 이 질문, 활성화 -verbose:class 모든 클래스에 대한 JVM 로그 정보가로드되며, 이는 더 복잡한 시나리오 및 응용 프로그램에서 클래스가 어디에서 오는지 이해하는 데 매우 도움이 될 수 있습니다.

당신이 얻는 출력은 거의 이것과 같이 보입니다 (해당 질문에서 복사) :

[Opened /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/sunrsasign.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jsse.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/jce.jar]
[Opened /usr/java/j2sdk1.4.1/jre/lib/charsets.jar]
[Loaded java.lang.Object from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.io.Serializable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.Comparable from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.CharSequence from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
[Loaded java.lang.String from /usr/java/j2sdk1.4.1/jre/lib/rt.jar]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top