簡體   English   中英

URLClassLoader是否正確遍歷MANIFEST.MF類路徑標頭?

[英]Does URLClassLoader traverse MANIFEST.MF Class-Path headers properly?

更新1:確實,URL格式的差異會導致錯誤。 這是一個顯示問題的單元測試(手工剪切和混淆;希望我什么都沒錯過):

@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
}

更新0:問題可能與兩個引用jar文件的URL之間的假定等效性有關,而不與實際等效性有關。 例如,以下兩個URL應該引用同一文件:

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

當我將從第一種格式構建的URL傳遞給我的機器時,我認為一切正常。 當我傳遞從第二種格式構建的URL時,得到以下描述的結果。 我正在做更多的測試以證實所有這些。

原始問題

(我知道這個問題 。)

我有一個jar文件waldo.jar ,其中包含如下所示的META-INF/MANIFEST.MF

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

它還在其中的以下位置有一個類:

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其中包含指向waldo.jar的URL。 回顧jimbo.jarjimbo.jar包含Jimbo並且是jimbo.jar “下一個”,並waldo.jarwaldo.jarMETA-INF/MANIFEST-MFClass-Path標頭中列出。 waldo.jar包含Waldo ,該代碼具有對Jimbo的代碼引用。 到目前為止和我在一起?

我可以加載com.foobar.Waldo很好。 但是,如果我對Waldo做一些涉及com.foobar.Jimbo ,例如調用Waldo.class.getDeclaredMethod("getJimbo")Waldo.class.getDeclaredMethod("getJimbo")收到NoClassDefFoundError 這是一個示例堆棧:

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)

這向我表明, URLClassLoader在所有情況下都沒有正確地查詢Class-Path標頭(我知道它通常如何工作的 )。

任何人都可以了解這里發生的事情嗎?

這是由於JDK中錯誤所致。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM