Вопрос по java – переносимый оператор для загрузки библиотеки JNI из другого каталога, используя относительный путь?

9

Существует ли независимый от платформы оператор Java для загрузки собственной библиотеки из каталога, отличного от исходного кода Java? Я хотел бы использовать что-то вроде этого:

public class HelloWorld {
    static {
        System.loadLibrary("../some_project/HelloWorld");
    }

    public static native void print();
}

Проблема состоит в том, что System.loadLibrary () не поддерживает разделители каталогов в аргументе pathname. Кроме того, System.load (), к сожалению, требует абсолютного пути, что не только означает, что я не могу указать относительный каталог, как указано выше (что я хотел бы сделать), но также требует, чтобы аргумент включал, например, предыдущий & Quot; Lib & Quot; и ".so" расширение имени библиотеки JNI в системе Linux.

Есть ли стандартный способ борьбы с этим? Если возможно, я бы хотел избежать написания связанного с платформой Java-кода просто для создания правильного имени библиотеки JNI.

Хорошо, спасибо, что указал на это. Я не знаю, как использовать путь относительно файла .jar, но чтобы не задавать второй вопрос в комментарии, я просто сделаю ссылку на несколько других вопросов stackoverflow, которые кажутся полезными: / Stackoverflow.com вопросы / 2837263 / ... / Stackoverflow.com вопросы / 5053150 / ... / Stackoverflow.com вопросы / 779650 / ... jvm_update
Не было бы более стабильным, если бы путь был относительно, например, ваш файл .jar, а не «текущий каталог». Это неизбежно приведет к проблемам в долгосрочной перспективе, если текущий каталог будет отличаться (например, из-за ярлыка на рабочем столе) a_horse_with_no_name
Первый квест (тот, который используетgetProtectionDomain()) является единственным правильным ответом на эту проблему. a_horse_with_no_name

Ваш Ответ

2   ответа
18

Я думаю, ты ищешь System.mapLibraryName, который обычно используется ClassLoader.findLibrary реализации. Например

File lib = new File("../some_project/" + System.mapLibraryName("HelloWorld"));
System.load(lib.getAbsolutePath());

Это будет использоватьlibHelloWorld.so в Linux иHelloWorld.dll в Windows. Имейте в виду, что некоторые операционные системы поддерживают несколько расширений, а mapLibraryName может поддерживать только одно из них. Я знаю о MacOS .dylib в первую очередь и.jnilib для наследия) и AIX .a а также.so).

Я обновил ответ, чтобы включитьgetAbsolutePath, Благодарность Brett Kail
+ 1 mapLibraryName - это фрагмент головоломки, о котором я ничего не знал David Heffernan
Благодарность! Это то, что я искал. Я только что попробовал, и это прекрасно работает. Просто для справки любого, кто читает это, System.load () требует абсолютного пути, поэтому каталог должен быть абсолютным и добавлен косая черта, например, с кодом: new java.io.File (". ./some_project / "). getCanonicalPath () +" / " jvm_update
0

loadLibrary. И так, что оставляload. Но это требует абсолютного пути. Итак, разверните ваш относительный путь в абсолютный путь, используя предпочитаемые вами служебные функции пути к файлу, и передайте его вload. Это может показаться неудобным, но это гораздо надежнее, чем полагаться на капризы путей поиска в библиотеке.

Развернуть его до абсолютного пути, как? Что еще более важно, как загрузка может быть выполнена переносимым способом? Библиотека будет иметь три разных имени файла на трех разных платформах: HelloWorld.dll (Windows), libHelloWorld.so (Linux) и libHelloWorld.jnilib (Mac OS X). Какая строка (строки) Java-кода автоматически выберет подходящее имя на соответствующей платформе, и я не буду жестко кодировать оператор switch в Java-коде? jvm_update
Ну, относительный путь относительно чего-то. Поэтому поместите это перед относительной частью, и вы получите свой абсолютный путь. Что касается расширения, я не знаю, есть ли что-то встроенное, но оно должно быть достаточно простым для определения платформы и переключения. David Heffernan
Моя цель - иметь возможность портировать приложение на новую платформу без необходимости перекомпиляции Java-части приложения. То есть скомпилированный код Java должен быть переносимым. Явная проверка того, в какой операционной системе работает код, к сожалению, не зависит от платформы. jvm_update
Тогда найди способ использовать loadLibrary в этом случае David Heffernan
Это именно то, о чем спрашивал оригинальный вопрос. jvm_update

Похожие вопросы