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

Обновлено: 07.07.2024

Репутация: 1
Всего: 2

Репутация: нет
Всего: 3

Если работаешь в Eclipse :
Project ->Properties -> Java Build Path ->Libraries

Репутация: 1
Всего: 2

Цитата

Если работаешь в Eclipse :
Project ->Properties -> Java Build Path ->Libraries

Прошу прощения, забыла указать - у меня IntelliJ Idea.

Leprechaun Software Developer

Репутация: 15
Всего: 534

Репутация: 1
Всего: 2

Leprechaun Software Developer

Репутация: 15
Всего: 534

P.S. У нас есть кнопка "Пометить вопрос как решённый", можешь смело ей пользоваться

Репутация: нет
Всего: нет

Добрый день! У меня возник тот же вопрос! Я использую Eclipse. Надо добавить dll-ку. Вот только в Project ->Properties -> Java Build Path ->Libraries не получается - там вижу возможность добавить только jar-файлы. (

Репутация: нет
Всего: 1

У меня аналогичная проблема, что и tusenok ,облазил все вкладки эклипса в окне Java Build Path, а как добавить *.dll файлы так и не понял.

Репутация: нет
Всего: 1

Решение для эклипса можно найти здесь : Добавить *.dll библиотеки в эклипс

  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux.

[ Время генерации скрипта: 0.1188 ] [ Использовано запросов: 21 ] [ GZIP включён ]

У меня есть собственная библиотека, которую нужно добавить в java.library.path . С аргументом JVM -Djava.library.path = path . я могу установить путь по своему усмотрению.

Моя проблема в том, что другая моя библиотека (отчеты pentaho) ищет шрифты на основе java.library.path по умолчанию (включая системные каталоги и т. Д.), А ручная настройка переопределяет путь по умолчанию ..

Итак: как я могу добавить запись пути к стандартному java.library.path вместо его переопределения (что, похоже, делается с помощью -Djava.library.path)? (Я бы не хотел вручную добавлять путь по умолчанию, что было бы нехорошо для развертывания)

РЕДАКТИРОВАТЬ: извините за недостающие детали; Я работаю с Eclipse. (Развертывание выполняется с помощью JNLP, и там я могу использовать nativelib под ресурсами )

Я забыл об этой проблеме . Я действительно спрашивал с Eclipse, извините за то, что не сказал об этом изначально. И ответ кажется слишком простым (по крайней мере, с 3.5; возможно, и со старыми версиями):

Аргументы конфигурации запуска Java: Аргументы виртуальной машины:

Не забывайте кавычки, иначе возникнут проблемы с пробелами в PATH.

Если вы хотите добавить собственную библиотеку без вмешательства в java.library.path во время разработки в Eclipse (чтобы избежать включения абсолютных путей и необходимости добавлять параметры в конфигурацию запуска), вы можете указать путь к расположению собственных библиотек для каждого Jar в диалоговом окне Путь сборки Java в разделе Расположение собственной библиотеки . Обратите внимание, что имя файла собственной библиотеки должно соответствовать имени файла Jar. См. Также это подробное описание.

SWT помещает необходимые собственные библиотеки DLL в JAR. Найдите пример по запросу "org.eclipse.swt.win32.win32.x86_3.4.1.v3449c.jar".

Библиотеки DLL должны находиться в корне JAR, JAR должен быть подписан, а DLL должна отображаться с контрольной суммой в файле META-INF / MANIFEST.MF, чтобы виртуальная машина могла их забрать.

В Windows вот так:

-Djava.library.path = "C: / MyLibPath;% PATH%"

% PATH% - это ваш старый -Djava.library.path

Можете ли вы обойти это, вызвав System.load () программно для загрузки собственной библиотеки? Этот метод (в отличие от System.loadLibrary ()) позволяет указать абсолютный путь.

Таким образом, (почти) невозможно добавить или добавить другую папку библиотеки к java.library.path при запуске Eclipse без предварительного знания настроек по умолчанию.

Я написал почти, потому что должна быть возможность запустить Eclipse, сбросить содержимое java.library.path и остановить Eclipse одной командой. Дамп будет проанализирован, а затем использован в качестве входных данных для запуска Eclipse, т.е.

В системах UNIX вы можете добавить к переменной среды LD_LIBRARY_PATH. В Windows JVM автоматически устанавливает для системного свойства java.library.path значение PATH; так что, если dll находится в вашем PATH, тогда все готово.

Окно-> Настройки-> Java-> Установленные JRE. Затем выберите текущую JRE (JDK) и нажмите «Изменить». Заполните параметры виртуальной машины по умолчанию: -Djava.library.path = / usr / local / xuggler / lib. Готово!

Решение, предложенное Робом Элснером в одном из комментариев выше, отлично работает (OSX 10.9, Eclipse Kepler). Нужно добавить их дополнительные пути к разделенным ":".

Вы также можете использовать $ - Роб Элснер, 22 ноября 2010 г., 23:01

По какой-то причине я не мог заставить работать несколько папок (ну, какое-то время это было так, но как только мне понадобилось больше dll и добавлено больше папок, ни одной с пробелами в пути). Затем я скопировал все необходимые библиотеки DLL в одну папку и использовал это как свой java.library.path , и это сработало. У меня нет объяснения - если у кого-то есть, было бы здорово.

Для этого я выполнил эти инструкции по запуску Eclipse из командной строки Java вместо его обычного средства запуска. Затем я просто изменил этот сценарий, чтобы добавить аргумент -Djava.library.path в командную строку Java.

  1. В Windows: добавьте путь к библиотеке в переменную среды PATH.
  2. В Linux: добавьте путь к библиотеке в переменную среды LD_LIBRARY_PATH.
  3. На Mac: добавьте путь к библиотеке в переменную среды DYLD_LIBRARY_PATH.

java.library.path инициализируется значениями указанных выше переменных на соответствующей платформе.

Это должно работать в любой среде IDE.

Вы можете проверить, соответствует ли значение ожидаемому, позвонив java -XshowSettings:properties

Я обнаружил, что в Windows важно запустить Eclipse из командной строки , а не из меню «Пуск» или ярлыка, при условии, что собственная DLL находится в каталоге в вашем PATH. По-видимому, это гарантирует, что правильный каталог находится на пути.

При вызове библиотеки java dll для начинающих часто возникают ошибки, такие как не загружаемая библиотека и метод, который не найден (UnsatisfiedLinkError и т. Д.). Эта статья подробно анализирует общие проблемы и дает более полное решение.

Тело:

Написать нативный метод в Java для реализации вызова DLL, общий процесс выглядит следующим образом:

Затем с помощью команды javah создайте файл заголовка и получите:

Создайте проект C (платформа Eclipse), скопируйте указанный выше заголовочный файл и запишите файл .c или .cpp для реализации собственного метода

Постройте, получите файл dll, измените его на name.dll и поместите в проект java.

После описанных выше способов, если вам повезет, это можно сделать один раз. Но следующие ошибки также распространены, и я классифицирую их по 3 категориям:

Ошибка типа A, файл dll не найден / не может быть загружен:

0.java.lang.UnsatisfiedLinkError: no XXX in java.library.path

1.java.lang.UnsatisfiedLinkError: Can't load library

2. UnsatisfiedLinkError: XXXXXXX не является допустимым приложением Win32.

Ошибка типа B, во всех успешно загруженных файлах DLL вызываемый метод не может быть найден:

Ошибка типа C, компилятор C.C / C ++ не может найти / не может проанализировать заголовочный файл jni.h:

Ошибка типа D, версия jvm конфликтует с dll:

0.ava.lang.UnsatisfiedLinkError: Невозможно загрузить 32-разрядную версию DLL IA на 64-разрядной платформе AMD. Этот тип ошибки легко понять, то есть 32-битная jvm использует 64-битную dll или наоборот. Это также относительно легко решить, обычно изменить соответствующую версию DLL или изменить версию JDK, но это более хлопотно.

Для вышеуказанных 4 типов проблем тип D относительно прост для решения и не будет объяснен снова.

Класс C: компилятор C.C / C ++ не может найти / не может проанализировать заголовочный файл jni.h

Этот тип ошибки не является проблемой написания нашего кода, это проблема платформы компиляции. Пока платформа компилятора знает, где найти этот заголовочный файл, это нормально. Для eclipse, если в качестве компилятора C используется mingw, лучшим решением будет поместить include / jni.h и include / win32 / jni_md.h в каталог jdk в папке mingw, в папке номера версии mingw. Например, в каталоге include мой каталог: D: \ Cbianyi \ mingw64 \ x86_64-w64-mingw32 \ include. Если вы используете VS6, вы можете добавить вышеуказанный каталог jdk в расположении ниже:


Если это VS2017, просто установите каталог включения. Лично рекомендую писать C-код, лучше использовать VS, VS6 также удобнее, чем Eclipse.

Класс A: ошибка поиска / загрузки dll

Мы загружаем dll, которая на самом деле включает в себя два процесса поиска и загрузки, из которых процесс поиска dll выполняется слоем java, а загрузка выполняется jvm.

A.0 и A.1 ищут dll: как правило, в ссылке "найти".

Есть два способа найти и загрузить dll: Общий метод - System.loadLibrary ("libname"), параметр - имя файла dll без суффикса (в дальнейшем именуемый sys.loadlib). Источник ошибки, как правило, в этом методе. Другой - использовать System.load («имя файла»), параметр - это абсолютный путь к dll с суффиксом (в дальнейшем именуемым sys.load). Если этот метод используется, он в принципе не ошибается, если путь не указан неправильно или есть проблема с самим файлом dll. Фактически, эти два метода в конечном итоге найдут dll по абсолютному пути, но для sys.loadlib java завершит это имя библиотеки как имя файла, а затем найдет его. Давайте посмотрим на исходный код.

Эти два метода встречаются в ClassLoader. LoadLibrary (Class <?> FromClass, String name, логическое значение isAbsolute) (в дальнейшем именуемый loader.load). При использовании метода sys.load параметр isAbsolute, передаваемый этому методу, имеет значение true со следующим исходным кодом:

Это показывает, что для sys.load, который дает абсолютный путь, java непосредственно найдет этот путь, если нет, он выдаст UnsatisfiedLinkError («Can't load library:» + name).

Если вы используете sys.loadlib, то isAbsolute имеет значение false, вы должны сначала завершить абсолютный путь. Процесс завершения является громоздким, и наиболее непосредственно связаны с нами:

Другими словами, завершенные пути являются содержимым двух массивов sys_path и use_paths. Если это не может быть найдено, он предложит UnsatisfiedLinkError ("нет" + имя + "в java.library.path"). Если мы не устанавливаем другие параметры, эти два пути представляют переменные среды jre и system соответственно. Очевидно, что если вы вызываете эти dll вне системы, вы можете поместить записанные dll в эти переменные среды. Кроме того, вы можете указать каталог java.library.path. Если указан этот каталог, в приведенном выше коде в usr_path будет только один каталог, а не системная переменная окружения. Есть много способов указать. Однако, поместив dll, который вы написали в переменную окружения (или установив ее как переменную окружения), и метод установки libpath, когда проект перемещается, изменяется и освобождается, dll не может быть найдена.

Решение, которое я дал, состоит в том, что вместо использования метода sys.loadlib дается «абсолютный путь». Точно так же мы не можем написать путь. Фактически, загрузка dll и входного потока файла, очень похожего, состоит в том, чтобы сначала найти файл, а затем прочитать его в память. Поэтому файл dll можно рассматривать как обычный файл ресурсов. Я считаю, что у программиста может быть несколько способов найти файл в проекте, независимо от того, как проект перемещен и выпущен. Метод, который я использую, состоит в том, чтобы сначала получить путь к классу, а затем соединить его в соответствии с относительными отношениями между путем к классу и путем к DLL. Таким образом, независимо от того, как проект перемещен и выпущен, проблем не будет. Следующим образом я помещу файл B32.dll для загрузки в каталог lib на том же уровне, что и Native:

Таким образом, вы можете гарантировать, чтобы найти DLL.

A.2 Загрузка DLL

Независимо от того, использовать ли относительный или абсолютный путь для поиска dll, когда эта dll найдена, jvm попытается загрузить dll в память через систему LoadLibrary системы Windows (в дальнейшем называемая win.load). Эта часть отделена от слоя Java. Чтобы подтвердить эту точку зрения, необходимы некоторые базовые знания о Си. Давайте сделаем отладку с ollydbg:


После добавления точки останова в bp LoadLibraryA после нескольких выпусков вы увидите:


Это FileName является именно той DLL, которая будет загружена.

Затем точка останова в ret, чтобы получить позицию отображения B32 в памяти:


Перейдите к 0x8B00000, чтобы увидеть память,


Можно определить, что B32.dll был успешно сопоставлен с памятью.

Кроме того, мы можем доказать, что пока имя файла B32.dll, jvm будет вызывать метод win.load и пытаться его загрузить. Создайте новый пустой текстовый файл, переименуйте его в B32.dll, по-прежнему отлаживая в соответствии с вышеуказанным способом, вы все равно можете получить:


Однако ret вернет 0, потому что это не действительный / легальный файл DLL, и программа сообщит об ошибке:



Кроме того, давайте проверим, что System.loadlibrary ("B32"), который загружается по имени файла, также завершит утверждение абсолютного пути. В этом предложении в исходном коде абсолютный путь не указан. Другие настройки не выполняются.

Параметры отладки следующие:


Параметры на рисунке: -Djava.library.path = "F: \ java32 \ jdk1.8.0_181 \ bin \ lib" Main, что означает указание java.library.path.

Также можно видеть, что конечная загрузка осуществляется по абсолютному пути.


B32 картографический адрес:


Но при использовании sys.loadlib система автоматически завершает суффикс как dll. В это время при использовании .exe при поиске выдает ошибку, и более поздний процесс загрузки не будет.

Краткое описание проблем класса А. Сначала Java ищет файл на основе заданного абсолютного пути или дополненного пути, если это так, JVM пытается загрузить файл. В это время, если файл является легальным dll (win32) Файл, процесс загрузки считается успешным. Если файл не существует или не является легальным файлом DLL (win32), произойдет ошибка.

Ошибка типа B, во всех успешно загруженных файлах DLL вызываемый метод не может быть найден:

Когда Java вызывает собственный метод, он отправляется в экспортированную таблицу имен всех успешно загруженных библиотек, чтобы найти соответствующее имя метода, и, если оно принято, его можно вызвать. Если вы не можете найти его, вы сообщите о такой проблеме. Конечно, когда JVM работает, его невозможно найти при каждом вызове, но есть набор методов обработки. Данные просматриваются через таблицу сопоставления адресов. Эта часть слишком низкого уровня для изучения. Давайте рассмотрим наиболее тесно связанные с ошибками класса B: пока имя метода, вызываемого java, находится в экспортированной таблице имен dll, его можно успешно вызывать. Есть два места, чтобы отметить и проверить здесь:

Во-первых, его можно найти в таблице имен экспорта. Это не просто означает, что этот метод существует в таблице имен экспорта, он также включает и может быть найден системой. Этот момент я объяснил в первой статье:dll экспортирует стратегию поиска таблицы имен, Эта проблема была также обнаружена в этой Java, и я не знал ее раньше.

Во-вторых, при вызове для сравнения используется только имя метода, независимо от параметров метода, типа возвращаемого значения и т. Д. Например, я хочу вызвать в java метод без параметров и без возвращаемого значения типа void say (), а то, что экспортируется в dll, это 3 параметра, скажем, int (arg1, arg2, arg3) типа возврата int, Это также можно назвать.

В-третьих, он успешно вызывается, но метод не гарантированно успешно выполняется.

Давайте проверим следующее:

Уровень Java остается неизменным, мы загружаем B32.dll и пытаемся вызвать собственный метод void say (String s). После того, как этот метод скомпилирован заголовочным файлом, вы получите:

extern "C" JNIEXPORT void JNICALL Java_Native_say (JNIEnv *, jclass, jstring). Другими словами, найдите метод Java_Native_say в B32.dll. Extern "C", JNIEXPORT и JNICALL - базовые знания языка Си, если вы не понимаете, вы можете проверить это сами.

Сначала мы делаем «рутинный» процесс. Метод в C:

После компиляции Dll, проверьте структуру PE, чтобы получить адрес памяти всего метода:


Отладка dbg, в соответствии с методом отладки, приведенным выше, находит запись метода, точки останова и одношаговой операции. Видно, что программа здесь запускается. Пять вызовов соответствуют put, printf, printf, env-> GetStringUTFChars и вставляет в исходный код C. За исключением того, что четвертый cal является преобразованием строки, остальные четыре будут получать каждый раз, когда они выполняются. Соответствующий вывод.

Это показывает, что метод Java, вызывающий dll, в памяти, должен перейти к соответствующему адресу памяти метода.

Исходя из этого, давайте проверим, что «при вызове для сравнения используется только имя метода, независимо от параметров метода, типа возвращаемого значения и т. Д.»

Слой Java остается неизменным, и мы удаляем оригинальный B32.dll. В окнах системного каталога просто найдите dll.


Вставьте его в наш каталог lib и переименуйте в B32.dll.

Затем измените имя функции этой таблицы имен экспорта dll на Java_Native_say. Принимая во внимание стратегию поиска в таблице имен dll, лучше изменить здесь первый элемент таблицы имен и использовать шестнадцатеричный редактор для его изменения.


Имя исходного первого элемента - «AccConvertAccessMaskToActrlAccess». Затем проверьте адрес функции еще раз:


Хорошо, начните отладку dbg. Получите адрес изображения этого псевдо "B32.dll", добавьте RVA и установите точку останова:


Объяснение действительно, чтобы ввести этот метод. Тогда отпусти и продолжай бежать, можно ошибаться. Тот, который мы изменили здесь, неправильный. Конечно, иногда это не пойдет не так, даже если модификаторы методов несовместимы.

Хорошо, теперь вы можете быть уверены, что метод вызова dll в java и метод вызова dll в программе на C в основном одинаковы: все они находятся в таблице экспорта dll и выполняются способом C.

Для нормальной разработки, согласно автоматически сгенерированному файлу .h, непосредственно скопируйте объявление метода, а затем сгенерируйте dll, почему я не могу его найти?

На самом деле, строго в соответствии с методом, который я дал выше, если вы компилируете 32-битную DLL, вы не можете найти ее. Для extern "C" JNIEXPORT void JNICALL Java_Native_say (JNIEnv *, jclass, jstring) это определение метода, независимо от eclipse, VS6, VS2017, именем экспортируемой таблицы будет _Java_Native_say @ 12, и вы не получите Java_Native_say. Я скомпилировал шестнадцатеричные данные и изменил имя метода, как я делал выше. Этот метод, очевидно, не работает. Если существует много методов экспорта, не было бы очень трудным изменить их один за другим. В Eclipse для редактирования C используется mingw. Если он 32-битный, то есть параметры, которые можно изменить, чтобы напрямую генерировать метод без дополнительных символов, для VS я не нашел метод. Если это 64-битная платформа, будь то Eclipse или VS, она будет напрямую генерировать «Java_Native_say».

Кроме того, скажем немного больше. При написании собственного исходного кода, если он не объявлен в файле заголовка или в .cpp / c, а только определен, тогда extern "C" JNIEXPORT void JNICALL Java_Native_say (JNIEnv *, jclass, jstring) должен быть завершен , Слово не может быть меньше: если оно объявлено сначала, а затем определено, жизнь должна быть гарантированно завершена, когда она определена, extern "C" JNIEXPORT может быть опущен, просто напишите void JNICALL Java_Native_say (JNIEnv *, jclass, jstring).

Наконец, после понимания содержания вопроса AB выше, мы можем предположить или проверить:

1. System.load / loadLibrary не должен быть записан в классе, где объявлен нативный метод, и не должен быть записан в static <>. В любом месте кода просто вызовите sys.load перед вызовом нативного метода. Просто поместите его в static <> собственного класса, чтобы гарантировать, что процесс загрузки не будет пропущен.

2. Вы можете загрузить несколько библиотек DLL: если в этих библиотеках есть метод с одинаковым именем, то метод в библиотеке DLL, который загружается в первый раз, будет вызван при его вызове.

Суммируйте основные моменты:

Во-первых: укажите точный путь, чтобы java мог найти файл dll; легальная dll, чтобы jvm мог успешно загрузить dll.

Второе: точное имя метода таблицы имен экспорта dll, чтобы JVM могла найти адрес памяти, на котором расположен собственный метод, и завершить вызов.

Так вот создаю.
Строка private native void ShowMessage(String msg); в соответствующем цвете и Java Virtual Machine Launcher
выдает


java.library.path - это путь к каталогу, где у тебя храниться твоя dll.

это если указывать через опцию -Djava.library.path (см. ссылку выше)

динамические библиотеки можно подключать из самого приложения:

Кроме того, имена функций в dll должны формироваться по определенному правилу(см. ссылку выше.)

1.the prefix Java_
2.a mangled fully-qualified class name
3.an underscore (“_”) separator
4.a mangled method name
5.for overloaded native methods, two underscores (“__”) followed by the mangled argument signature

The VM checks for a method name match for methods that reside in the native library. The VM looks first for the short name; that is, the name without the argument signature. It then looks for the long name, which is the name with the argument signature. Programmers need to use the long name only when a native method is overloaded with another native method. However, this is not a problem if the native method has the same name as a nonnative method. A nonnative method (a Java method) does not reside in the native library.


java.library.path - это путь к каталогу, где у тебя храниться твоя dll.

это если указывать через опцию -Djava.library.path (см. ссылку выше)

динамические библиотеки можно подключать из самого приложения:

Кроме того, имена функций в dll должны формироваться по определенному правилу(см. ссылку выше.)

1.the prefix Java_
2.a mangled fully-qualified class name
3.an underscore (“_”) separator
4.a mangled method name
5.for overloaded native methods, two underscores (“__”) followed by the mangled argument signature

The VM checks for a method name match for methods that reside in the native library. The VM looks first for the short name; that is, the name without the argument signature. It then looks for the long name, which is the name with the argument signature. Programmers need to use the long name only when a native method is overloaded with another native method. However, this is not a problem if the native method has the same name as a nonnative method. A nonnative method (a Java method) does not reside in the native library.

но никто не мешает написать свой враппер в виде DLL, оформленой соовтетствующим образом, и вызывать уже его методы. Это, конечно, скажется на производительности. Пример из книжки:

Java класс, использующий dll

Код враппера вызывающего функцию из целевой dll.

НА изучение уйдет много времени. Поэтому не примите за дерзость, прошу помощи в виде наставлений. Я не прошу написания кода, помогите просто подсказками. Может в результате получится какое нибудь руководство по использованию dll в Java. ДЛЯ ЧАЙНИКОВ.

Итак. У меня есть dll. И два файла *.h.
В первом список функций из dll, а другой состоит из конструкций типа и в нем описываются коды ошибок.

Теперь пытаюсь делать обвязку своей dll. Т.е. создам dll для Java, которая будет вызывать функции первой dll.
В Вorland С++ Builder 6 . Т.к моя dll работает с USB девайсом (содержит команды по управлению устройством), то выбираю

Пока писал пример вы уже почти разобрались :)
То, что бросилось в глаза:

Как вы собрираетесть из java передавать эту структуру в

Для нее надо бы заводить отдельный класс c native методами для доступа к полям и хранить в нем указатель на native структуру. Тогда при передаче экземпляра этого класса в native метод в качестве параметра сможете получить указатель на структуру и передать его в качестве параметра в нужную функцию.

Вот у нас есть java класс.

javac Native.java
javah Native

и получаем то, о чем мы с Вами говорим - Native.h:

С этим тоже разобрался. Наклепал

javac - это компилятор java.

Надо не javac -jni, а javah -jni

если запускать в D:\Native\ надо

javah -jni Native

-jni - нужен в java 1.4, а в 1.5 - эта опция включена по умолчанию.

Читайте также: