java - 如何避免调用 System.load 两次?

标签 java java-native-interface

我有一个类,它调用 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/

相关文章:

java - 无法解析encodetoString

java - Android外部库访问

java - 找不到合适的 native 库。 native.libpath.* 与 java.library.path

c++ - Android JNI bridge Toast C++ 不工作——如何解决?

java - Play 2 JPA Oracle - 即使 ebeanEnabled 在 build.scala 中设置为 false,也会出现额外列 'ebean_intercept'

java - 如何在 Web ui 中更新使用服务帐户 api 上传的 Google Drive 文档?

java - 将 GWTquery 与 GWT 结合使用

java - 在请求负载中设置字符串列表

java - vc++ JNI错误LNK2019 : unresolved external symbol

java - 使用 nar-maven-plugin 将外部 .so 库添加到 jni 项目