我正在编写一个程序来加载指定文件夹中的所有类。
有些类在静态块中创建对象,而这些对象又在创建过程中进行一些本机调用。由于我没有本机库,我看到了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
我在这里加载A类来检查它的一些属性,比如它的Super Classes等。所以我甚至不在乎是否创建了B :) 既然在给定的文件夹中可以有很多像A这样的类,那么是否有一种通用的方法可以确保像A这样的类的加载不会失败?
更新:我知道本地库需要存在以及如何添加它。但我没有本地库,因此我要求这个黑客。
答案 0 :(得分:3)
实现本机功能的.DLL或.so需要位于系统路径上。 VM将调用loadlibrary来加载相关的.dll / .so,如果找不到,它将抛出UnsatisfiedLinkError。
您可以捕获UnsatisfiedLinkError以忽略该问题,但您将无法使用依赖于它的类。
如果要检查类但不实际使用它们,可以使用Java Dissasembeler, javap。您可以以编程方式访问所需的功能 - javap在包sun.tools.javap中定义,实现在$ JDK \ lib \ tools.jar
答案 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());
}
}
答案 2 :(得分:1)
您必须修改A以使其不再依赖于B,否则修改B以使其不再依赖本机代码,或者替换B。
具体来说,您可以使用自定义ClassLoader
并手动加载您自己的B版本,该版本与提供的版本不同,因为它没有任何本机依赖项。然后在同一个ClassLoader
中加载A,然后按照自己的意愿执行操作。
答案 3 :(得分:1)
也许您可以编写生成,编译和加载缺少的本机库的模拟版本?看起来好像很多工作。
答案 4 :(得分:0)
为什么没有本机库的课程?如果无法初始化基类,则派生类将不起作用。使用-Djava.library.path指定本机库的位置。