使用 module-info.java 时无法加载 FFI 提供程序

Posted

技术标签:

【中文标题】使用 module-info.java 时无法加载 FFI 提供程序【英文标题】:Could not load FFI provider when using module-info.java 【发布时间】:2020-09-17 08:39:04 【问题描述】:

我的 Linux Java 应用程序使用蓝牙设备。我使用这个库来与 bluez stack 通信:https://github.com/hypfvieh/bluez-dbus.

在我将module-info.java 添加到我的客户端代码之前,它运行良好。突然出现这个错误:

线程“主”java.lang.UnsatisfiedLinkError 中的异常:无法加载 FFI 提供程序 jnr.ffi.provider.jffi.Provider 在 jnr.ffi@2.1.15/jnr.ffi.provider.InvalidRuntime.newLoadError(InvalidRuntime.java:101) 在 jnr.ffi@2.1.15/jnr.ffi.provider.InvalidRuntime.findType(InvalidRuntime.java:42) 在 jnr.ffi@2.1.15/jnr.ffi.Struct$NumberField.(Struct.java:872) 在 jnr.ffi@2.1.15/jnr.ffi.Struct$Unsigned16.(Struct.java:1240) 在 jnr.unixsocket@0.33/jnr.unixsocket.SockAddrUnix$DefaultSockAddrUnix.(SockAddrUnix.java:209) 在 jnr.unixsocket@0.33/jnr.unixsocket.SockAddrUnix.create(SockAddrUnix.java:174) 在 jnr.unixsocket@0.33/jnr.unixsocket.UnixSocketAddress.(UnixSocketAddress.java:53) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.transports.UnixSocketTransport.(UnixSocketTransport.java:32) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.transports.TransportFactory.createTransport(TransportFactory.java:37) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.AbstractConnection.(AbstractConnection.java:161) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.(DBusConnection.java:334) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:149) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:169) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:219) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:184) 在 bluez.dbus@0.1.3/com.github.hypfvieh.bluetooth.DeviceManager.createInstance(DeviceManager.java:74) 在...

原因:java.lang.UnsatisfiedLinkError: could not get native definition for type POINTER, 原始错误信息如下:java.lang.UnsatisfiedLinkError: could not locate stub library in jar file。试过 [jni/x86_64-Linux/libjffi-1.2.so, /jni/x86_64-Linux/libjffi-1.2.so] 在 jffi@1.2.23/com.kenai.jffi.internal.StubLoader.getStubLibraryStream(StubLoader.java:450) 在 jffi@1.2.23/com.kenai.jffi.internal.StubLoader.loadFromJar(StubLoader.java:375) 在 jffi@1.2.23/com.kenai.jffi.internal.StubLoader.load(StubLoader.java:278) 在 jffi@1.2.23/com.kenai.jffi.internal.StubLoader.(StubLoader.java:487) 在 java.base/java.lang.Class.forName0(本机方法) 在 java.base/java.lang.Class.forName(Class.java:427) 在 jffi@1.2.23/com.kenai.jffi.Init.load(Init.java:68) 在 jffi@1.2.23/com.kenai.jffi.Foreign$InstanceHolder.getInstanceHolder(Foreign.java:49) 在 jffi@1.2.23/com.kenai.jffi.Foreign$InstanceHolder.(Foreign.java:45) 在 jffi@1.2.23/com.kenai.jffi.Foreign.getInstance(Foreign.java:103) 在 jffi@1.2.23/com.kenai.jffi.Type$Builtin.lookupTypeInfo(Type.java:242) 在 jffi@1.2.23/com.kenai.jffi.Type$Builtin.getTypeInfo(Type.java:237) 在 jffi@1.2.23/com.kenai.jffi.Type.resolveSize(Type.java:155) 在 jffi@1.2.23/com.kenai.jffi.Type.size(Type.java:138) 在 jnr.ffi@2.1.15/jnr.ffi.provider.jffi.NativeRuntime$TypeDelegate.size(NativeRuntime.java:178) 在 jnr.ffi@2.1.15/jnr.ffi.provider.AbstractRuntime.(AbstractRuntime.java:48) 在 jnr.ffi@2.1.15/jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:57) 在 jnr.ffi@2.1.15/jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:41) 在 jnr.ffi@2.1.15/jnr.ffi.provider.jffi.NativeRuntime$SingletonHolder.(NativeRuntime.java:53) 在 jnr.ffi@2.1.15/jnr.ffi.provider.jffi.NativeRuntime.getInstance(NativeRuntime.java:49) 在 jnr.ffi@2.1.15/jnr.ffi.provider.jffi.Provider.(Provider.java:29) 在 java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) 在 java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) 在 java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) 在 java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) 在 java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:124) 在 java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:346) 在 java.base/java.lang.Class.newInstance(Class.java:604) 在 jnr.ffi@2.1.15/jnr.ffi.provider.FFIProvider$SystemProviderSingletonHolder.getInstance(FFIProvider.java:68) 在 jnr.ffi@2.1.15/jnr.ffi.provider.FFIProvider$SystemProviderSingletonHolder.(FFIProvider.java:57) 在 jnr.ffi@2.1.15/jnr.ffi.provider.FFIProvider.getSystemProvider(FFIProvider.java:35) 在 jnr.ffi@2.1.15/jnr.ffi.Runtime$SingletonHolder.(Runtime.java:82) 在 jnr.ffi@2.1.15/jnr.ffi.Runtime.getSystemRuntime(Runtime.java:67) 在 jnr.unixsocket@0.33/jnr.unixsocket.SockAddrUnix.(SockAddrUnix.java:46) 在 jnr.unixsocket@0.33/jnr.unixsocket.SockAddrUnix$DefaultSockAddrUnix.(SockAddrUnix.java:208) 在 jnr.unixsocket@0.33/jnr.unixsocket.SockAddrUnix.create(SockAddrUnix.java:174) 在 jnr.unixsocket@0.33/jnr.unixsocket.UnixSocketAddress.(UnixSocketAddress.java:53) 在 dbus.java@3.2.3/org.freedesktop.dbus.connections.transports.UnixSocketTransport.(UnixSocketTransport.java:32) 在...

我试图在 module-info.java 中要求与此错误相关的所有内容,但没有成功:

module org.example 
    requires dbus.java;
    requires dbus.java.nativefd;
    requires bluecove.linux.custom;
    requires bluez.dbus;
    requires jnr.ffi;
    requires jnr.x86asm;
    requires jnr.posix;
    requires jnr.enxio;
    requires jnr.unixsocket;
    requires jnr.constants;
    requires jnr.a64asm;

提前谢谢你。

【问题讨论】:

【参考方案1】:

TL;DR

这对我有用……

java --patch-module jffi=your.own.location/com/github/jnr/jffi/1.3.0/jffi-1.3.0-native.jar …

长版

我下载了this example project。这不是 JPMS 项目。但是我在四个子项目中的每一个中添加了 module-info.java 文件。

我将项目的 com.github.jnr:jnr-ffi 依赖项从 2.0.9 更新为 2.1.5 以匹配我在堆栈跟踪中看到的版本.我添加了以下依赖项...

…
<dependency>
    <groupId>com.github.hypfvieh</groupId>
    <artifactId>dbus-java</artifactId>
    <version>3.2.3</version>
</dependency>
<dependency>
    <groupId>com.github.hypfvieh</groupId> <artifactId>bluez-dbus</artifactId>
    <version>0.1.3</version>
</dependency>
<dependency>
    <groupId>com.rm5248</groupId>
    <artifactId>dbus-java-nativefd</artifactId>
    <version>1.0</version>
</dependency>
…

添加这些是为了让我可以将我的四个 module-info.java 描述符中的每一个都定义为与您的非常相似……

module get.pid
    exports getpid;
    requires dbus.java;
    requires dbus.java.nativefd;
    requires bluez.dbus;
    requires jnr.ffi;
    requires jffi;
    requires jnr.x86asm;
    requires jnr.posix;
    requires jnr.enxio;
    requires jnr.unixsocket;
    requires jnr.constants;
    requires jnr.a64asm;

在我执行 --patch-module 之前,我运行了一个示例项目并得到了与您完全相同的错误。

但是使用以下命令,所有示例应用程序都可以作为模块完美运行……

java --patch-module jffi=your.own.location/com/github/jnr/jffi/1.3.0/jffi-1.3.0-native.jar --add-modules org.objectweb.asm --add-exports org.objectweb.asm/org.objectweb.asm=jnr.ffi --add-exports org.objectweb.asm/org.objectweb.asm.signature=jnr.ffi --module-path path.to.all.the.jars -m get.pid/getpid.Getpid

add-modulesadd-exports 也很重要。所以不要遗漏这些。

【讨论】:

以上是关于使用 module-info.java 时无法加载 FFI 提供程序的主要内容,如果未能解决你的问题,请参考以下文章

Java 9 + maven + junit:测试代码是不是需要自己的 module-info.java 以及放在哪里?

如何从 checkstyle 插件检查中排除 module-info.java?

4.eclipse中导入别人用的源代码问题

创建java project是需不需要创建一个module-info.JAVA file

如何在模块化Java应用程序中使用SynthLookAndFeel?

SPI + JDK 9 + 模块信息.java