2009-12-29 63 views
3

我正在寫一個程序,加載指定文件夾中的所有類。加載一個具有本地代碼依賴性的Java類

某些類正在靜態塊中創建對象,並且這些對象反過來在創建過程中進行一些本地調用。由於我沒有本地庫,所以我看到一個java.lang.UnsatisfiedLinkError

這是一個示例場景。

Class A extends SuperA 
{ 
    public static B b = new B(); 
    ... 
    ... 
} 

Class B 
{ 
    public B() 
    { 
     someNativeCall(); // Causing the LinkError 
    } 
} 

Class.forName("A"); // Loading of Class A 

我加載的類在這裏檢查它的一些屬性,如它的超類等等,所以我如果創建B沒有甚至不關心或不:) 因爲可以有很多類,比如在給定的文件夾中,是否有一種通用的方法來確保像A這樣的類的加載不會失敗?

更新:我知道本地庫需要存在以及它需要如何添加。但我沒有本地圖書館,因此正在尋求這種破解。

+0

在運行時,可以我們確定所有的類如B,並注入模擬的B對象?我不知道一種方法來實現它。 – Varun 2009-12-29 15:03:03

+0

另請參閱http://stackoverflow.com/questions/1029559/java-system-loadlibrarysomedllfile-gets-unstatisfied-link-error – finnw 2009-12-29 15:09:41

+0

我已經實現的解決方案:javap可以通過編程方式訪問,但API不是很清楚。最後使用了http://jakarta.apache.org/bcel/manual.html,它們具有類似於java反射的清晰API。 – Varun 2009-12-30 10:42:22

回答

3

實現本機函數的.DLL或.so需要位於系統路徑中。虛擬機將調用loadlibrary加載相關的.dll/.so,如果沒有找到,它會拋出一個UnsatisfiedLinkError。

您可以捕獲UnsatisfiedLinkError以忽略該問題,但您將無法使用依賴它的類。

如果您想檢查這些類,但實際上並未使用它們,則可以使用Java Dissasembeler, javap。您可能能夠以編程方式訪問您需要的功能 - javap在包sun.tools.javap中定義,並且實現位於$ JDK \ lib \ tools.jar中

+1

請注意,它不需要位於系統路徑中,僅在JVM路徑中。請參閱上面提到的Java啓動標誌。 – whatnick 2009-12-29 15:03:37

+0

我沒有與我的本地庫。由於我不想運行應用程序,只需要加載一堆類,我正在尋找破解 – Varun 2009-12-29 15:07:43

+1

@whatnick非常正確 - 您可以使用任一種方法 - 儘管使用java.library.path會更具體/安全的存在多個版本的庫。 – 2009-12-29 15:08:09

0

爲什麼您有沒有本機庫的類?如果基類無法初始化,派生類將無法工作。使用-Djava.library.path指定本地庫的位置。

+0

本地庫的不可用性是整個問題。如果可用,我會添加它:) – Varun 2009-12-29 15:04:54

+0

本地庫的目的是什麼,也許它可以用類似的東西替代? – Esko 2009-12-29 16:12:03

1

你必須要麼修改,使其不再依賴於B,否則修改B上不再對本地代碼的依賴,否則更換B.

具體地說,可以使用自定義的ClassLoader並手動加載您自己的B版本,與提供的版本不同,因爲它沒有任何本機依賴關係。然後在你的相同ClassLoader中加載A,然後按照你的要求做。

+0

@丹非常有趣。你能否請進一步解釋一下。 – Varun 2009-12-30 05:24:01

1

也許你可以編寫代碼生成,編譯和加載缺失本機庫的模擬版本?看起來像很多工作,雖然。

2

還有的Class.forName過載,它可以讓你指定你是否要初始化類或沒有(和你不這樣做,如果你只是想反映這一點):

class X { 

    static { if (true) throw new ExceptionInInitializerError("OH NOES!!!"); } 

} 

public class Y { 
    public static void main(String[] args) throws Throwable{ 
     // Breaks: 
     System.out.println(Class.forName("X").getSuperclass()); 
     // Works: 
     ClassLoader cl = Thread.currentThread().getContextClassLoader(); 
     System.out.println(Class.forName("X", false, cl).getSuperclass()); 
    } 
} 
+0

謝謝。我不知道這個API。這會工作得很好:) – Varun 2013-10-21 18:55:23

相關問題