我需要从依赖项扩展Maven的类构建,但是它将作为最终类添加。
我必须使用.dll库作为资源来构建jar。加载它们的代码不是我写的,并且作为Maven依赖项包含在项目中。我在加载这些库时遇到了麻烦。在IntelliJ中,我将.dll库的路径添加到项目结构中。当我将代码作为IntelliJ类运行时,一切正常。
当我想运行打包的jar时,问题开始了。我使用maven-assembly-plugin。它正在工作(已加载所有依赖项),但是我仍然无法加载这些库。
我想出了一个方法来覆盖由我自己负责查找这些库的类,但是它们是最终类,因此我无法对其进行扩展。
是否可以更改其签名?
负责加载库的类的一部分:
public final class Hub {
private static final File TEMP_DIRECTORY_LOCATION = new File(System.getProperty("java.io.tmpdir"));
private long nativeHandle;
private final String applicationIdentifier;
public Hub() {
this("");
}
public Hub(String applicationIdentifier) {
this.applicationIdentifier = applicationIdentifier;
loadJniResources();
initialize(applicationIdentifier);
}
private final void loadJniResources() {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("mac")) {
boolean wasLoadSuccessful = loadOSXResourceFromSysPath();
if (!wasLoadSuccessful) {
wasLoadSuccessful = copyAndLoadOSXFromTemp();
if (!wasLoadSuccessful) {
throw new UnsatisfiedLinkError("Could Not Load myo and myo-java libs");
}
}
} else if (osName.contains("win")) {
boolean wasLoadSuccessful = loadX64ResourcesFromSysPath();
if (!wasLoadSuccessful) {
wasLoadSuccessful = loadWin32ResourcesFromSysPath();
if (!wasLoadSuccessful) {
setLibDirectory();
wasLoadSuccessful = copyAndLoadX64FromTemp();
if (!wasLoadSuccessful) {
wasLoadSuccessful = copyAndLoadWin32FromTemp();
if (!wasLoadSuccessful) {
throw new UnsatisfiedLinkError("Could Not Load myo and myo-java libs");
}
}
}
}
} else {
System.err.println("Your Operating System is not supported at this time.");
}
}
private void setLibDirectory() {
try {
System.setProperty("java.library.path", TEMP_DIRECTORY_LOCATION.getAbsolutePath());
Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
fieldSysPath.setAccessible(true);
fieldSysPath.set(null, null);
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean loadX64ResourcesFromSysPath() throws UnsatisfiedLinkError {
try {
System.loadLibrary("myo64");
System.loadLibrary("JNIJavaMyoLib");
return true;
} catch (UnsatisfiedLinkError e) {
String errorMessage = String.format("Unable to load myo64 from system directories.");
System.err.println(errorMessage);
}
return false;
}
private boolean copyAndLoadX64FromTemp() {
try {
File myo64DllTempFile = new File(TEMP_DIRECTORY_LOCATION, "myo64.dll");
myo64DllTempFile.deleteOnExit();
try (InputStream myo64DllInputStream = this.getClass().getResourceAsStream("/x64/myo64.dll")) {
Files.copy(myo64DllInputStream, myo64DllTempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
File jniJavaMyoLibDllTempFile = new File(TEMP_DIRECTORY_LOCATION, "JNIJavaMyoLib64.dll");
jniJavaMyoLibDllTempFile.deleteOnExit();
try (InputStream jniJavaMyoLibDllInputStream = this.getClass().getResourceAsStream("/x64/JNIJavaMyoLib.dll")) {
Files.copy(jniJavaMyoLibDllInputStream, jniJavaMyoLibDllTempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
}
System.loadLibrary("myo64");
System.loadLibrary("JNIJavaMyoLib64");
return true;
} catch (UnsatisfiedLinkError e) {
String errorMessage = String.format("Unable to load %s from directory %s.", "myo64.dll", TEMP_DIRECTORY_LOCATION);
System.err.println(errorMessage);
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
}
错误消息:
在第一次尝试连接设备时:
Unable to load myo64 from system directories.
Unable to load myo32 from system directories.
第二次尝试连接设备时
Unable to load myo64 from system directories.
Unable to load myo32 from system directories.
java.nio.file.AccessDeniedException: C:\Users\Anka\AppData\Local \Temp\myo64.dll
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:97)
at sun.nio.fs.WindowsException.rethrowAsIOException(WindowsException.java:102)
at sun.nio.fs.WindowsFileSystemProvider.implDelete(WindowsFileSystemProvider.java:269)
at sun.nio.fs.AbstractFileSystemProvider.deleteIfExists(AbstractFileSystemProvider.java:108)
at java.nio.file.Files.deleteIfExists(Files.java:1165)
at java.nio.file.Files.copy(Files.java:3004)
at com.thalmic.myo.Hub.copyAndLoadX64FromTemp(Hub.java:184)
at com.thalmic.myo.Hub.loadJniResources(Hub.java:67)
at com.thalmic.myo.Hub.<init>(Hub.java:27)
at pl.pollub.controller.device.DeviceTask$2.call(DeviceTask.java:54)
at pl.pollub.controller.device.DeviceTask$2.call(DeviceTask.java:49)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at pl.pollub.controller.device.DeviceTask$1.call(DeviceTask.java:31)
at pl.pollub.controller.device.DeviceTask$1.call(DeviceTask.java:27)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)
Unable to load myo32.dll from directory C:\Users\Anka\AppData\Local\Temp.
java.lang.UnsatisfiedLinkError: C:\Users\Anka\AppData\Local\Temp\myo32.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at com.thalmic.myo.Hub.copyAndLoadWin32FromTemp(Hub.java:222)
at com.thalmic.myo.Hub.loadJniResources(Hub.java:69)
at com.thalmic.myo.Hub.<init>(Hub.java:27)
at pl.pollub.controller.device.DeviceTask$2.call(DeviceTask.java:54)
at pl.pollub.controller.device.DeviceTask$2.call(DeviceTask.java:49)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at pl.pollub.controller.device.DeviceTask$1.call(DeviceTask.java:31)
at pl.pollub.controller.device.DeviceTask$1.call(DeviceTask.java:27)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1423)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.lang.Thread.run(Thread.java:748)