当前,我正在尝试在Raspberry Pi 3上使用蓝牙,在尝试使用其他未完成的库后,我选择了DBus(快照2.1.1)上的BlueCove,因为它似乎已经完成并且并没有强制使用GPL许可证。不幸的是,给定的编译库没有包含ARM的本机,因此经过反复试验,我编译了该API的本机及其先决条件。还是我想。
我在尝试使用API时收到UnsatisfiedLinkError。我可以确认该库正在加载到JVM中,并且在调用本机方法时出现错误。
java.lang.UnsatisfiedLinkError:com.intel.bluetooth.BluetoothStackBlueZDBus.getLibraryVersionNative()I 在com.intel.bluetooth.BluetoothStackBlueZDBus.getLibraryVersionNative(本机方法) 在com.intel.bluetooth.BluetoothStackBlueZDBus.getLibraryVersion(BluetoothStackBlueZDBus.java:160) 在com.intel.bluetooth.BlueCoveImpl.detectStack(BlueCoveImpl.java:471) 在com.intel.bluetooth.BlueCoveImpl.access上获得$ 500(BlueCoveImpl.java:69) 在com.intel.bluetooth.BlueCoveImpl $ 1.run(BlueCoveImpl.java:1044) 在java.base / java.security.AccessController.doPrivileged(本机方法) 在com.intel.bluetooth.BlueCoveImpl.detectStackPrivileged(BlueCoveImpl.java:1042) 在com.intel.bluetooth.BlueCoveImpl.getBluetoothStack(BlueCoveImpl.java:1035) 在javax.bluetooth.LocalDevice.getLocalDeviceInstance(LocalDevice.java:75) 在javax.bluetooth.LocalDevice.getLocalDevice(LocalDevice.java:95) 在tech.delta.system_automation.server.bin.connections.bluetooth.RemoteDeviceDiscovery.discoverDevices(RemoteDeviceDiscovery.java:54) 在tech.delta.system_automation.server.bin.Autonoma_Server.main(Autonoma_Server.java:40)
这是我初始化流程的地方
LocalDevice d = LocalDevice.getLocalDevice();
这是BlueCove API中Java代码失败的地方
private native int getLibraryVersionNative();
public int getLibraryVersion() throws BluetoothStateException {
int version = getLibraryVersionNative();
if (version != BLUECOVE_DBUS_VERSION) {
DebugLog.fatal("BlueCove native library version mismatch " + version + " expected " + BLUECOVE_DBUS_VERSION);
throw new BluetoothStateException("BlueCove native library version mismatch");
}
return version;
}
这是它试图使用的C代码
JNIEXPORT jint JNICALL Java_com_intel_bluetooth_BluetoothStackBlueZDBus_getLibraryVersionNative
(JNIEnv *env, jobject peer) {
return com_intel_bluetooth_BluetoothStackBlueZDBus_BLUECOVE_DBUS_VERSION;
}
现在,我只能假设该代码在带有预编译本机的x86 / 64系统上使用时可以运行,但是我运气不佳,老实说,我没有使用JNI和C语言的经验知识有限,我一生中都没有写过Makefile。但是我怀疑这可能是C方面的链接问题。
我正在考虑在编译C代码时出现标志问题,该代码拒绝使用其编译的jar。我怀疑是因为必须将lib文件从libbluecovez.so重命名为libbluecovez_arm.so。但是我不确定,我正在寻找一些经验丰富的用户,这些用户可能会指出正确的方向。
以下是供参考的Makefile
# @version $Revision: 2829 $ ($Author: skarzhevskyy $) $Date: 2009-03-03 03:44:45 -0500 (Tue, 03 Mar 2009) $
#
# Created by Francois Kooman
#
# Use this file in case you don't have ant or maven installed on the system
# Usage: make all
#
BLUECOVE_VERSION=2.1.1-SNAPSHOT
BLUECOVE_JAR=../bluecove/target/bluecove-${BLUECOVE_VERSION}.jar
JAVAH=$(JAVA_HOME)/bin/javah
JAVAC=$(JAVA_HOME)/bin/javac
JAVAC_OPTIONS=-g -source 1.5 -target 1.5
CC=gcc
CFLAGS=-Wall -fPIC -fno-stack-protector # -Werror
# -nodefaultlibs -> statically linked
CLIBFLAGS=$(CFLAGS) -nodefaultlibs -shared -Wl,-soname,libbluecovez-$(BLUECOVE_VERSION)
SRC_C_DIR=src/main/c
SRC_JAVA_DIR=src/main/java
CLASSES_DIR=target/classes
OBJ_DIR=target/native
JAVACLASSES=com.intel.bluetooth.BluetoothStackBlueZDBus com.intel.bluetooth.BluetoothStackBlueZDBusConsts com.intel.bluetooth.BluetoothStackBlueZDBusNativeTests org.bluecove.socket.LocalSocketImpl
LIBPOSTFIX=`uname -p | grep 64 | sed 's/.*64.*/_x64/g'`
TARGET_LIB=target/libbluecovez$(LIBPOSTFIX).so
DBUS_JAVA_LIBS_DIR=target
DBUS_JAVA_CLASSPATH=$(DBUS_JAVA_LIBS_DIR)/dbus.jar:$(DBUS_JAVA_LIBS_DIR)/unixsockets.jar
CLASSPATH=$(BLUECOVE_JAR):$(DBUS_JAVA_CLASSPATH)
all: classes jni-headers native-lib
classes:
-@mkdir -p $(CLASSES_DIR)
-@$(JAVAC) -d $(CLASSES_DIR) $(JAVAC_OPTIONS) -classpath $(CLASSPATH) \
$(SRC_JAVA_DIR)/org/bluez/*.java $(SRC_JAVA_DIR)/com/intel/bluetooth/*.java $(SRC_JAVA_DIR)/org/bluecove/socket/*.java
jni-headers:
-@$(JAVAH) -d $(SRC_C_DIR) \
-classpath $(CLASSPATH):$(CLASSES_DIR) \
$(JAVACLASSES)
native-lib:
-@mkdir -p $(OBJ_DIR)
-@cd $(OBJ_DIR) && \
$(CC) $(CFLAGS) -c ../../$(SRC_C_DIR)/*.c -I${JAVA_HOME}/include -I${JAVA_HOME}/include/linux
-@$(CC) $(CLIBFLAGS) -o $(TARGET_LIB) $(OBJ_DIR)/*.o
-@strip $(TARGET_LIB)
-@cp $(TARGET_LIB) $(CLASSES_DIR)/libbluecovez$(LIBPOSTFIX).so
-@echo "Native library $(TARGET_LIB) created"
-@echo "Shared library dependencies:"
-@ldd -v $(TARGET_LIB)
clean:
rm -rf target
我怀疑Makefile中的行是
CLIBFLAGS=$(CFLAGS) -nodefaultlibs -shared -Wl,-soname,libbluecovez-$(BLUECOVE_VERSION)
和
TARGET_LIB=target/libbluecovez$(LIBPOSTFIX).so
考虑到最终的jar称为bluecove-bluez-2.1.1-SNAPSHOT.jar,而lib文件称为libbluecovez_arm.so
如果有人可以给我一些帮助,那就太好了。
更新,所以问题出在我的Makefile上,导致Javah出现问题,而Javah又导致C编译器出现问题,并且是我问题的根源。
这是编译错误
Error: Could not find class file for 'com.intel.bluetooth.BluetoothStackBlueZDBus'.
Error: Could not find class file for 'com.intel.bluetooth.BluetoothStackBlueZDBusConsts'.
Error: Could not find class file for 'com.intel.bluetooth.BluetoothStackBlueZDBusNativeTests'.
Error: Could not find class file for 'org.bluecove.socket.LocalSocketImpl'.
Makefile:40: recipe for target 'jni-headers' failed
make: [jni-headers] Error 1 (ignored)
In file included from ../../src/main/c/BlueCoveBlueZ.c:26:0:
../../src/main/c/BlueCoveBlueZ.h:38:57: fatal error: com_intel_bluetooth_BluetoothStackBlueZDBus.h: No such file or di rectory
#include "com_intel_bluetooth_BluetoothStackBlueZDBus.h"
^
compilation terminated.
In file included from ../../src/main/c/BlueCoveBlueZ_L2CAP.c:26:0:
../../src/main/c/BlueCoveBlueZ.h:38:57: fatal error: com_intel_bluetooth_BluetoothStackBlueZDBus.h: No such file or di rectory
#include "com_intel_bluetooth_BluetoothStackBlueZDBus.h"
^
compilation terminated.
In file included from ../../src/main/c/BlueCoveBlueZ_L2CAPServer.c:26:0:
../../src/main/c/BlueCoveBlueZ.h:38:57: fatal error: com_intel_bluetooth_BluetoothStackBlueZDBus.h: No such file or di rectory
#include "com_intel_bluetooth_BluetoothStackBlueZDBus.h"
^
compilation terminated.
In file included from ../../src/main/c/BlueCoveBlueZ_RFCOMM.c:26:0:
../../src/main/c/BlueCoveBlueZ.h:38:57: fatal error: com_intel_bluetooth_BluetoothStackBlueZDBus.h: No such file or di rectory
#include "com_intel_bluetooth_BluetoothStackBlueZDBus.h"
^
compilation terminated.
In file included from ../../src/main/c/BlueCoveBlueZ_RFCOMMServer.c:26:0:
../../src/main/c/BlueCoveBlueZ.h:38:57: fatal error: com_intel_bluetooth_BluetoothStackBlueZDBus.h: No such file or di rectory
#include "com_intel_bluetooth_BluetoothStackBlueZDBus.h"
^
compilation terminated.
In file included from ../../src/main/c/BlueCoveBlueZ_Tests.c:26:0:
../../src/main/c/BlueCoveBlueZ.h:38:57: fatal error: com_intel_bluetooth_BluetoothStackBlueZDBus.h: No such file or di rectory
#include "com_intel_bluetooth_BluetoothStackBlueZDBus.h"
^
compilation terminated.
In file included from ../../src/main/c/BlueCoveLocalSocket.c:27:0:
../../src/main/c/BlueCoveLocalSocket.h:40:49: fatal error: org_bluecove_socket_LocalSocketImpl.h: No such file or dire ctory
#include "org_bluecove_socket_LocalSocketImpl.h"
^
compilation terminated.
因此,我需要修改Makefile,使其正确指向.java文件?我不确定。
答案 0 :(得分:0)
对于其他遇到相同问题的人。 由于某种原因,原始的make文件在项目布局中无法与现代Java一起使用。 这将导致编译错误,导致无法生成.class文件。反过来,这意味着Javah(从Java 10开始不推荐使用)在尝试生成供本机库通过JNI进行通信的头文件时失败。 c编译器会忽略缺少头文件的情况,因此仍会进行编译。这导致了通用链接器错误。该文件在那里,但编译时未包含Java头文件。
要解决此问题,我在Windows系统上编译了jar罐Bluecove-bluez,从make文件中删除了编译类,同时清理了目标,然后将类从Windows系统直接复制到了目标,并将其复制到了我当时使用的闪存驱动器中。编译。 将闪存驱动器移至ARM Linux系统,仅编译头文件以及c natives即可解决此问题。