2016-10-06 2 views
0

UPDATE 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を渡すとき、私は物事を考える

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

:たとえば、次の2つのURLが同じファイルを参照することになっています作業しています。私が第2フォーマットから構築したURLを渡すと、私は以下の結果を得ます。私は疑問の余地なくこれをすべて確認するためにさらにテストしています。

元の質問

(私はthis questionの認識しています。)

私はこのようになりますMETA-INF/MANIFEST.MFが含まれているjarファイル、waldo.jar、持っている:

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

をまた、その中の次の場所にクラスがあります。

com/foobar/Waldo.class 

クラスのソースコードは、基本的に次のとおりです。

com/foobar/Jimbo.class 

package com.foobar; 

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

次に、同じディレクトリに、私はその中に次の場所にクラスが含まれているjarファイル、jimbo.jarを、持っています

そのクラスのソースコードは、基本的に次のとおりです。

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が得られます。ここではサンプルスタックは次のとおりです。

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は(私はhow it works in generalの承知している)すべての場合に適切にClass-Pathヘッダーに相談されていないことを私に示唆しています。

ここで何が起こっているのか誰にも光を当てはめることができますか?

+0

'Waldo.class.getDeclaredMethod(" getJimbo ")'の代わりに 'new Jimbo()'を試してみると、結果はどうなりますか? –

+0

クラスローダーを使っているクラスは 'ジンボ'について知らないので、私は 'new Jimbo()'を実行できません。 'jimbosClass.newInstance()'はほとんど確実に失敗します。私はそれを調べるために私のテストを再加速します。しかし、調整しておいてください。問題は 'URLClassLoader'に提供されたURLフォーマットであるようです:' jar:file:/myjar.jar!/ 'の代わりに' file:/ myjar.jar'を使用すると(同等であると思われます)すべてが機能するように見えます。 –

+0

私はこの瓶が手動で生成されると思います。そのクラスを含むフォルダのエントリがありません。 jarファイルにエントリ(ファイル構造のインデックスの種類)を追加するだけで動作します。 – user1615664

答えて

関連する問題