2016-10-06 2 views
0

업데이트 1 : 실제로 URL 형식의 차이로 인해 오류가 발생합니다. 여기에 단위 테스트는 (잘라 손으로 난독 화, 나는 아무것도 놓치지 않았다 희망) 문제 보여주는 :URLClassLoader가 MANIFEST.MF 클래스 경로 헤더를 제대로 트래버스합니까?

@Test 
public void wheresWaldo2() throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException, NoSuchMethodException { 
    // Find Waldo from file:/someLocation/waldo.jar. Prove that works. 
    URL waldosJar = new File("/someLocation/waldo.jar").toURI().toURL(); 
    assertNotNull(waldosJar); 
    assertEquals("file", waldosJar.getProtocol()); 
    String waldosPath = waldosJar.getPath(); 
    assertNotNull(waldosPath); 
    assertTrue(waldosPath.endsWith("/waldo.jar")); 

    ClassLoader cl = new URLClassLoader(new URL[] { waldosJar }, this.getClass().getClassLoader()); 

    Class<?> waldosClass = cl.loadClass("com.foobar.Waldo"); 
    assertNotNull(waldosClass); 
    assertEquals("com.foobar.Waldo", waldosClass.getName()); 
    assertSame(cl, waldosClass.getClassLoader()); 

    Class<?> jimbosClass = cl.loadClass("com.foobar.Jimbo"); // Note: works 
    assertNotNull(jimbosClass); 

    // Find Waldo from jar:file:/someLocation/waldo.jar!/. Prove that works. 
    // This URL, when passed to a URLClassLoader, should result in the same 
    // functionality as the first one. But it doesn't. 
    waldosJar = new URL("jar:" + waldosJar.toExternalForm() + "!/"); 
    assertEquals("jar", waldosJar.getProtocol()); 
    assertEquals("file:" + waldosPath + "!/", waldosJar.getPath()); 

    cl = new URLClassLoader(new URL[] { waldosJar }, this.getClass().getClassLoader()); 

    waldosClass = cl.loadClass("com.foobar.Waldo"); 
    assertNotNull(waldosClass); 
    assertEquals("com.foobar.Waldo", waldosClass.getName()); 
    assertSame(cl, waldosClass.getClassLoader()); 

    jimbosClass = cl.loadClass("com.foobar.Jimbo"); // XXX FAILS 
} 

UPDATE 0 :이 문제는 있지만 실제되지는 생각으로해야 할 수 있습니다를, jar 파일을 참조하는 2 개 (살)의 등가. 예를 들어, 다음 두 URL은 같은 파일을 참조로되어있다 : 내 기계에 대한 첫 번째 형식에서 구축 된 URL을 전달하는 경우

  • file:/myjar.jar
  • jar:file:/myjar.jar!/

, 내가 생각하는 것들 일하고있다. 두 번째 형식으로 작성된 URL을 전달하면 아래에 설명 된 결과가 나타납니다. 이 모든 것을 의심 할 여지없이 확인하기 위해 더 많은 테스트를하고 있습니다. 또한

Manifest-Version: 1.0 
Class-Path: jimbo.jar 

그것을 :

원래의 질문에

는 (. 내가 this question 알고있다)

나는이 jar 파일은, waldo.jar, 즉 다음과 같이 보이는 META-INF/MANIFEST.MF을 포함 다음 위치에 수업이 있습니다.

com/foobar/Waldo.class 

클래스 '소스 코드는 본질적으로 :

package com.foobar; 

public class Waldo { 
    public Jimbo getJimbo() { 
    return null; 
    } 
} 

그 다음 위치에서 클래스가 포함되어 다음과 같은 디렉토리에, 내가 가지고있는 jar 파일, jimbo.jar :

com/foobar/Jimbo.class 

그 클래스의 소스 코드는 본질적으로 :

package com.foobar; 

public class Jimbo { 

} 

지금 나는 URLClassLoader를 구성 URL은 waldo.jar입니다. 검토를 위해 : jimbo.jarJimbo을 포함하며 "waldo.jar"옆에 있으며 waldo.jarMETA-INF/MANIFEST-MFClass-Path 헤더에 적절하게 나열되어 있습니다. waldo.jarWaldo을 포함하며 코드 참조는 Jimbo입니다. 지금까지 나와 같이?

com.foobar.Waldo을로드 할 수 있습니다. 하지만 Waldocom.foobar.Jimbo과 관련되어 있는데, 예를 들어 Waldo.class.getDeclaredMethod("getJimbo")으로 전화를 걸면 NoClassDefFoundError이됩니다. URLClassLoader 모든 경우 (내가 how it works in general 알고 있어요)에 제대로 Class-Path 헤더 컨설팅되지 않도록

java.lang.NoClassDefFoundError: com/foobar/Jimbo 
    at java.lang.Class.getDeclaredMethods0(Native Method) 
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) 
    at java.lang.Class.getDeclaredMethod(Class.java:2128) 
    at com.foobar.TestClassLoadingProblems.wheresWaldo(TestClassLoadingProblems.java:115) 

    Caused by: 
    java.lang.ClassNotFoundException: com.foobar.Jimbo 
     at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
     at com.foobar.MyClassLoader.findClass(...) // calls super.findClass() 
     at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 

이 나에게 제안 : 다음은 샘플 스택이다.

여기에 무슨 일이 일어나고 있는지 알려줄 수 있습니까?

+0

'Waldo.class.getDeclaredMethod ("getJimbo")'대신'new Jimbo()'를 사용하면 결과는 어떻게됩니까? –

+0

classloader를 사용하는 클래스가'Jimbo '에 대해 알지 못하기 때문에'new Jimbo()'를 확실히 할 수 없습니다. 'jimbosClass.newInstance()'는 거의 실패 할 것입니다. 나는 그것을 시험하기 위해 나의 시험을 재촉 할 것이다. 계속 지켜봐라. 문제는'URLClassLoader'에 제공되는 URL 포맷과 관련이있는 것 같습니다 :'jar : file : /myjar.jar! /'대신'file :/myjar.jar'을 사용하면 (그들은 동등한 것으로 생각됩니다), 모든 것이 제대로 작동하는 것처럼 보입니다. –

+0

좋아,이 항아리가 수동으로 생성 된 것 같습니다. 폴더가있는 폴더의 항목이 누락되었습니다. jar 파일에 엔트리 (파일 구조의 인덱스 종류)를 추가하면됩니다. – user1615664

답변

관련 문제