2014-04-19 89 views
0

我正嘗試使用Javassist來加載從運行時從JAR文件動態加載的抽象方法類。出於某種原因,此代碼只能在Windows操作系統上運行。我在任何其他平臺上遇到ClassDefNotFoundException。這是我使用的代碼。Java - 如何動態實例化JAR中的抽象類?

public static void example() throws Exception { 
    String pathToJar = "pathToJar.jar"; 
    File JARFile = new File(pathToJar); 
    ClassLoader classLoader = URLClassLoader.newInstance(new URL[]{ JARFile.toURI().toURL() }); 
    Class<?> callBackClass = classLoader.loadClass("package.Callback"); 

    ProxyFactory factory = new ProxyFactory(); 
    factory.setSuperclass(callBackClass); 
    MethodHandler handler = new MethodHandler() { 

     @Override 
     public Object invoke(Object self, Method overridden, Method forwarder, 
       Object[] args) throws Throwable { 
      return forwarder.invoke(self, args); 
     } 
    }; 

    factory.setFilter(
      new MethodFilter() { 
       @Override 
       public boolean isHandled(Method method) { 
        return Modifier.isAbstract(method.getModifiers()); 
       } 
      } 
      ); 
    Object instance = factory.create(new Class<?>[0], new Object[0], handler); /*exception thrown here on non-windows OS*/ 
} 

這是類加載器的問題嗎?或者它是Javassist的問題?它應該與平臺無關,但取決於操作系統,它可能運行也可能不運行。

+0

什麼是抽象的? – Batty

+0

上述代碼中顯示的方法處理程序是抽象類。它覆蓋了invoke()方法,該方法應該被轉發給動態加載的方法類。問題是我行,factory.create()方法g – user3435571

+0

異常堆棧跟蹤,請。 – chrylis

回答

1

例外這裏扔在非Windows操作系統

這是一個很大的線索,這表明有一個資本差異的地方。與Windows一起使用的主要文件系統不區分大小寫,而其他地方使用的主要文件系統(* nix)區分大小寫。因此,仔細查看您要加載的資源大小,並確保您加載的代碼在代碼中的大小與在jar或文件系統中的大小相同。

+0

大小寫在所有平臺上都是正確的。我使用一個幫助程序庫來爲我檢索文件路徑,並使用適當數量的後退/前進斜槓。 – user3435571

+0

@ user3435571:是的,但是代碼中的包和類名稱如何? (並且斜槓與什麼有關?) –

+0

我的意思是字符串路徑名中的斜槓。在windows中,它是層次結構中的兩個反斜槓,而在類似UNIX的平臺上,它是一個正斜槓。包和類名稱也是等效的。 – user3435571

0

類不能被發現,並導致異常是

javassist.util.proxy.ProxyObject 

你確定你有在非Windows操作系統的類路徑上正確的罐子?代理對象接口由javassist創建的任何類實現。它似乎對類加載器不可見。您是否嘗試定義明確的class loader provider

我同意另一個答案,即套管是最可能的原因。你可以提供與你運行應用程序的命令和罐子的確切文件名嗎?

+0

引發的例外之一我相信它是。我實際上已經推斷這個問題實際上存在於URLClassLoader而不是ProxyObject中。我試圖鏈接的JAR文件是一個安裝了Gurobi優化的文件。出於某種原因,如果JAR文件的pathspec是錯誤的,那麼classLoader.loadClass方法不會拋出異常,但classLoader類(元素數量)不會增加。即使JAR的pathspec是正確的,我也會得到相同的結果。 URLClassLoader加載該類而不實際加載它,並將空引用(或具有null的容器)傳遞給代理 – user3435571

+0

與類加載器相比,它無法在其查找中找到該類。當無法找到或讀取資源時,類加載器永遠不會拋出IO異常,但會捕獲該異常並返回空引用。這可能也會導致noclassdeffounder錯誤,它不會引用原始的ioexception。 –

+0

問題是,當我嘗試加載類時,classLoader根本不會拋出任何異常,即使我不加載該JAR。兩種方式,類數不會增加 - 它應該拋出ClassNotFoundException,但它不會。出於某種原因,這隻會發生在Gurobi JAR中,而不是其他一種(並且只有在安裝時)。另外,如果我在將依賴項移動到另一個文件夾並從新位置加載後卸載Gurobi,那麼classLoader會正常工作(proxyObject也是如此)。然後,如果我指定了錯誤的JAR,它會拋出classNotFoundException。爲什麼是這樣? – user3435571