如何配置加载JNA的库

时间:2016-12-09 08:41:45

标签: jna

我使用JNA加载本机库:

MyLibrary INSTANCE = (MyLibrary) Native.loadLibrary("mylibrary.so", MyLibrary.class);

现在我想清理并处理库。我已经阅读了dispose方法,但这是在课程NativeLibrary上定义的,我应该如何称呼它?

无论如何,是否有必要这样做?我大规模地使用jna和Apache Spark,所以我加载了数千次库,我想知道如果我做的话,有任何资源可以打开{{1 }}?

编辑:我已经看到问题Jna, Unload Dll from java class dynamically,但它没有解决我的问题。

没有接受的答案。人们建议拨打dispose,但NativeLibrary.dispose()中没有这样的静态方法。如果我尝试转换我的库实例(类型为NativeLibrary),那么我会得到一个类转换异常。

2 个答案:

答案 0 :(得分:3)

您的帖子暗示您主要关注资源消耗。加载它并不需要考虑数千次" - 它很像静态变量,一旦加载就不会重新加载。

如果你想卸载它,你基本上有三个选择。

选项1:

INSTANCE = null;
System.gc(); // or simply wait for the system to do this

无法保证将收集对象,但通过将INSTANCE设置为null,您可以允许系统回收其资源。 (dispose()方法作为对象的finalize()方法的一部分进行调用,因此在最终收集对象时会将其处理掉。)如果您真的完成了实例,这对你来说已经足够了。请注意,如果重新加载库是其他行为所必需的,则不应该依赖此操作,因为无法保证垃圾收集。

选项2:

INSTANCE = null;
NativeLibrary lib = NativeLibrary.getInstance("mylibrary.so");
lib.dispose();

这将显式处理本机库,如果您需要重新加载库以强制重新加载编程行为(而不是重用现有实例),这将是首选方法。请注意,如果在加载库时使用了选项你也需要在这个调用中使用相同的选项。

选项3:使用NativeLibrary.disposeAll()。这会卸载您的所有库。根据您使用的其他库的数量(再次使用时必须重新加载),这可能对您有用。

请注意,在所有这些选项中,您可能需要在处置后稍微延迟一段时间,以确保本机操作系统也会释放其引用。

答案 1 :(得分:0)

我想添加另一个选项

  • 不依赖垃圾收集器
  • 仅使用公共 API
  • 具有最佳的可供性

我想有一个直接在库接口上处理库的方法,所以我们添加一个:

interface MyLibrary extends Library {

  // other methods omitted

  void dispose()
}

在实例化库时,我会为这个新方法创建一个调用处理程序:

final Map<String, Object> options = new HashMap<>();
options.put(Library.OPTION_INVOCATION_MAPPER, new InvocationMapper() {
  @Override
  public InvocationHandler getInvocationHandler(NativeLibrary lib, Method m) {
    if (m.getName().equals("dispose")) {
      return (proxy, method, args) -> {
        lib.dispose();
        return null;
      };
    }
    return null;
  }
});

return Native.load("/path/to/my/lib", MyLibrary.class, options);

然后用法如下:

public void cleanup(MyLibrary lib) {
  // other cleanup work
  lib.dispose();
}

这就是 MyLibrary 的客户无需了解 JNA 的任何内部结构即可正确处置库的方式。