我有一个类,它调用 native 函数来从 CMOS 获取有关系统的信息。该类有一个静态初始化 block ,它加载包含 native 函数的库,它看起来像这样:
package lib.sysid;
public class SysId
{
private static native int getSysIdNative();
private static final String SYS_ID_PATH = "libsysid.so";
static
{
System.load(SYS_ID_PATH);
}
public static int getSysIdFromCMOS()
{
int returnValue = getSysIdNative();
}
}
根据我的测试,该方法第一次使用时工作正常,但如果稍后再次调用该方法,静态初始化 block 也会运行,导致 UnsatisfiedLinkError:
java.lang.UnsatisfiedLinkError: Native Library libsysid.so already loaded in another classloader
如果已经运行了 System.load()
方法,如何避免静态初始化 block 执行?
或者,如果在再次调用 System.load()
方法之前已经加载了库,有没有办法让我尝试“卸载”该库?
编辑:奇怪的是,如果我用 try-catch block 包围 System.load()
调用,我仍然会收到 UnsatisfiedLinkError,但这一次它来自对 的实际调用>getSysIdNative()
。我看到的错误如下:
lib.sysid.SysId.getSysIdNative()I
出现的“我”到底是什么?我尝试将调试器附加到此代码以查看消息填充的位置,但到目前为止我还没有成功。
最佳答案
只是一个猜测,但我认为单个 JVM 加载一个类(并执行其静态初始化器)两次的唯一方法是使用不同的类加载器加载它。因此,这里可能涉及到您不知道的第二个类加载器。如果第二次使用不同的(一组)类加载器,则这将适用。
在“真实”操作系统下,java -verbose:class
会给您加载程序消息来验证这一点。我不确定您如何在嵌入式系统上验证这一点。您可以修改 getSysId()
以打印 (?) 或以某种方式转储对 SysId.class.getClassLoader()
的引用。
关于java - 如何避免调用 System.load 两次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3338531/