Java library path как туда добавить
Перейти к содержимому

Java library path как туда добавить

  • автор:

Java library path как туда добавить

Есть моя java либа. Она вызывает определенную dll. Хочется упаковать эту dll внутри jar файла, чтобы пользующиеся этой dll вообще не думал ни про какие нейтивы. Не очень понятно как это сделать.

dll то я положил внутрь jar по пути WEB-INF/native, как делают многие. Вот только когда я делаю System.loadLibrary — это все ищется в java.library.path, и никак иначе. Явно просить пользователя библиотеки выставлять java.library.path, копировать туда dll и тому подобное — ИМХО не самое дружелюбное решение. Единственное приемлемое решение вижу — при инициализации либы копировать из ресурсов либу в темповую директорию, добавлять эту темповую директорию в java.library.path, при закрытии за собой подчищать, но это такой изврат, что нет слов.

Как это вообще делать по феншую?

Настройка java.library.path в проекте Eclipse: путь решения

Чтобы задать java.library.path в Eclipse, воспользуйтесь параметрами виртуальной машины (VM Arguments) следующим образом:

-Djava.library.path=/путь/к/вашей/библиотеке

Вы должны указать актуальный путь к папке с нативными библиотеками вместо /путь/к/вашей/библиотеке . Пройдите в меню Run Configurations, выберите вкладку Arguments и введите нужный вам параметр. После применения изменений ваш проект будет запущен с новыми настройками.

Пошаговый гид по настройке java.library.path в Eclipse

Правильная настройка java.library.path крайне важна, когда вы работаете с внешними нативными библиотеками. Детально рассмотрим процесс настройки.

Изменение Java Build Path

Проходите к Properties > Java Build Path и переходите на вкладку Libraries. Отышите требуемую библиотеку, разверните её меню и выберите пункт Native library location, затем нажмите Edit и определите путь.

Настройка Run Configurations для отдельных проектов

Настроить java.library.path возможно с помощью Run Configurations для конкретного проекта:

JNI, загрузка нативных библиотек. Меняем java.library.path на лету

В подмножестве экосистемы Java, относящейся в основном к JNI (без которого никуда не деться, если приходиться интегрироваться с каким-то legacy или просто редким и специфическим кодом, написанном на С или каком-то другом языке), есть такое понятие, как java.library.path. Вкратце, это в некотором роде аналог classpath, только не для Java классов и *.jar файлов, а для нативных библиотек — системное свойство, которое указывает JVM, где искать эти самые нативные библиотеки (.dll в винде или .so под юниксами).

Свойство это устанавливается один раз, перед запуском JVM, через глобальные system properties, или как ключ -Dname=value для JVM, и после этого оно становится read-only. Точнее, менять-то его можно, но никакого эффекта на работу программы это не окажет, т.к. после того как вы обновите это свойство, JVM не перечитает его и не будет использовать новое значение.

Под катом — про то, как все таки поменять это свойство в рантайме, и немного о том, как собственно работает загрузка нативных библиотек в Java.

Однако, возможность менять java.library.path на лету была бы очень кстати — тогда бы не пришлись много раз генерить, переписывать и перезаписывать скрипты для запуска JBoss-a, например, чтобы отразить в них все нужные пути ДО старта аппсервера.

И такая возможность, изменять эти пути, по которым JVM ищет нативные библиотеки, на самом деле есть. Конкретные приемы показаны тут — blog.cedarsoft.com/2010/11/setting-java-library-path-programmatically и еще вот тут — nicklothian.com/blog/2008/11/19/modify-javalibrarypath-at-runtime.

А здесь я опишу сам механизм загрузки, и почему то, что описано по ссылкам, работает. Обычно, нативные библиотеки загружаются через статический инициализатор:

* This source code was highlighted with Source Code Highlighter .

Который выглядит так:

public static void loadLibrary( String libname) Runtime.getRuntime().loadLibrary0(getCallerClass(), libname);
>

* This source code was highlighted with Source Code Highlighter .

И далее в классе Runtime:

synchronized void loadLibrary0(Class fromClass, String libname) // Проверяем, разрешено ли загружать данную конкретную библиотеку
SecurityManager security = System.getSecurityManager();
if (security != null ) security.checkLink(libname);
>
if (libname.indexOf(( int ) File .separatorChar) != -1) throw new UnsatisfiedLinkError( «Directory separator» +
«should not appear in library name: » + libname);
>
ClassLoader.loadLibrary(fromClass, libname, false );
>

* This source code was highlighted with Source Code Highlighter .

Т.е. в итоге, нативные библиотеки загружаются, так же как и обычные классы, через ClassLoader. У класса ClassLoader есть два свойства, в которых кешируются проинициализированные пути поиска.

// The paths searched for libraries
static private String usr_paths[];
static private String sys_paths[];

* This source code was highlighted with Source Code Highlighter .

Код метода ClassLoader.loadLibrary(fromClass, libname, false), довольно длинный, и загроможденный многочисленными проверками, в сокращенном виде выглядит это так.

// Invoked in the java.lang.Runtime class to implement load and loadLibrary.
static void loadLibrary(Class fromClass, String name,
boolean isAbsolute)

ClassLoader loader = (fromClass == null ) ? null : fromClass.getClassLoader();
if (sys_paths == null ) // это то, что нам нужно
usr_paths = initializePath( «java.library.path» );

// а это для тех библиотек, которые загружаются из классов,
// загруженных из boot classpath.
sys_paths = initializePath( «sun.boot.library.path» );
>

// Дальше попытка загрузить библиотеку, и дальше,
// если найти ее так и не удалось, то —
// Oops, it failed
throw new UnsatisfiedLinkError( «no » + name + » in java.library.path» );
>

* This source code was highlighted with Source Code Highlighter .

Таким образом, теперь механизм загрузки нативной библиотеки стал более понятен.

Вы можете либо выставить в null свойство sys_paths у класслоадера, либо просто поменять свойства sys_paths / usr_paths, добавив к ним нужные пути к вашим нативным библиотекам.

Java library path как туда добавить

3 декабря 2023

Привет! Подскажите, в чем Разница между Paths.get and Path.of? Как по мне они идентичны. И проще везде использовать Path.of)

alex1 Уровень 23

28 октября 2023

Статья удалена или нужен впн, чтобы ее почитать? https://annimon.com/article/2778

Anonymous #2447435 Уровень 29

28 сентября 2023

Подскажите, почему у меня в консоль ничего не выводится? Вроде бы, создал структуру файлов и папок, и код набил такой же:

 package com.javarush.test.InputOutputStreams; import javax.naming.directory.BasicAttribute; import java.io.IOException; import java.nio.file.*; import java.util.List; public class filesWalkFileTreeVar1 < public static void main(String[] args) throws IOException < Files.walkFileTree(Paths.get("D:\\SeReGA\\J A V A R U S H\\testFolder"), new MyFileVisitor()); >> class MyFileVisitor extends SimpleFileVisitor implements FileVisitor < @Override public FileVisitResult visitFile(Path file, BasicAttribute attr) throws IOException < Listlines = Files.readAllLines(file); for (String s: lines) < if (s.contains("This is the file we need")) < System.out.println("Нужный файл обнаружен!"); System.out.println(file.toAbsolutePath()); break; //return FileVisitResult.TERMINATE; >> return FileVisitResult.CONTINUE; > > 

Never Ending Pie Throwing Robot Уровень 30

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *