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

Существует ли независимый от платформы оператор 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.

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

Ответы на вопрос(2)

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

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

Я думаю, ты ищешь 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).

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

Ваш ответ на вопрос