Почему не загружается кастомная 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 шт):

Автор решения: Art3

Получилось это все сделать с помощью использования 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. Может есть более простой способ добиться желаемого результата, но к этому моменту я нашел только такой.

→ Ссылка