Почему не загружается кастомная dll после jlink?
Пишу проект на javafx с использованием jna 5.7.0, в Intellij idea все запускается и работает, но как только собираю с помощью jlink и запускаю .bat файл вылетает ошибка.
Вот мой main метод в котором я указываю где искать мои dll:
public static String getPathToDll(String filename) throws URISyntaxException {
return Paths.get(App.class.getResource(filename + ".dll").toURI()).toAbsolutePath().getParent().toString();
}
public static void main(String[] args) throws Exception {
System.setProperty("jna.debug_load", "true");
if (Platform.getOSType() == Platform.WINDOWS) {
if (Platform.is64Bit()) {
NativeLibrary.addSearchPath("DrivesLib", getPathToDll("DrivesLib"));
NativeLibrary.addSearchPath("ftd2xx64", getPathToDll("ftd2xx64"));
TRSG2 trsg2 = Native.load("ftd2xx64", TRSG2.class);
} else {
NativeLibrary.addSearchPath("DrivesLib32", getPathToDll("DrivesLib32"));
NativeLibrary.addSearchPath("ftd2xx", getPathToDll("ftd2xx"));
}
Application.launch(args);
}
}
С помощью System.setProperty("jna.debug_load", "true"); и запуска приложения через Intellij в консоле я получаю следующее сообщение:
���. 09, 2021 1:23:47 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Looking for library 'ftd2xx64'
���. 09, 2021 1:23:47 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Adding paths from jna.library.path: null
���. 09, 2021 1:23:47 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Trying D:\projects\Intellij projects\GenerationCenter\target\classes\com\example\ftd2xx64.dll
���. 09, 2021 1:23:47 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Found library 'ftd2xx64' at D:\projects\Intellij projects\GenerationCenter\target\classes\com\example\ftd2xx64.dll
И я вижу, что действительно моя dll нашлась, успешно загрузилась и приложение запустилось. О чем свидетельствует сообщение:
INFO: Found library 'ftd2xx64' at D:\projects\Intellij projects\GenerationCenter\target\classes\com\example\ftd2xx64.dll
Но как только я собираю все с помощью jlink и запускаю программу через .bat, то получаю следующее в консоль:
Mar 09, 2021 1:30:27 PM com.sun.jna.Native extractFromResourcePath
INFO: Looking in classpath from jdk.internal.loader.ClassLoaders$AppClassLoader@7591083d for /com/sun/jna/win32-x86-64/jnidispatch.dll
Mar 09, 2021 1:30:28 PM com.sun.jna.Native extractFromResourcePath
INFO: Found library resource at jrt:/com.sun.jna/com/sun/jna/win32-x86-64/jnidispatch.dll
Mar 09, 2021 1:30:28 PM com.sun.jna.Native extractFromResourcePath
INFO: Extracting library to C:\Users\User\AppData\Local\Temp\jna-2645995\jna15888007890012122786.dll
Mar 09, 2021 1:30:28 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Looking for library 'ftd2xx64'
Mar 09, 2021 1:30:28 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Adding paths from jna.library.path: null
Mar 09, 2021 1:30:28 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Trying ftd2xx64.dll
Mar 09, 2021 1:30:28 PM com.sun.jna.NativeLibrary loadLibrary
INFO: Loading failed with message: ═х эрщфхэ єърчрээ√щ ьюфєы№.
В чем может быть ошибка и как это можно исправить?
Ответы (1 шт):
Получилось это все сделать с помощью использования getResourceAsStream в методе getPathToDll:
public static InputStream getPathToDll(String filename) {
return App.class.getResourceAsStream("lib/" + filename + ".dll");
}
А далее просто создать временный файл с полученного InputStream и вернуть путь к этому файлу:
private static String createTempDllReturnPath(String filename) {
File out = null;
try (InputStream is = getPathToDll(filename)) {
if (is != null) {
String tempDir = System.getProperty("java.io.tmpdir");
out = new File(tempDir, filename + ".dll");
out.deleteOnExit();
try (FileOutputStream fos = new FileOutputStream(out)) {
byte[] buf = is.readAllBytes();
fos.write(buf, 0, buf.length);
}
}
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(out.getParent());
return out.getParent();
}
А в main методе заменить: NativeLibrary.addSearchPath("DrivesLib", getPathToDll("DrivesLib")); на NativeLibrary.addSearchPath("DrivesLib", createTempDllReturnPath("DrivesLib"));
Теперь это работает как при запуске приложение в Intellij, так и после сборки с помощью jlink. Может есть более простой способ добиться желаемого результата, но к этому моменту я нашел только такой.