Java.lang.UnsatisfiedLinkError no *****. dll в java.library.path
Как загрузить пользовательский DLL файл в моем веб-приложении? Я пробовал следующие способы, но не смог.
- скопировал все необходимые DLL файлы в папку
system32
и попытался загрузить один из них в конструктор Servlet
System.loadLibrary
- Скопированные требуемые DLL в
tomcat_home/shared/lib
и tomcat_home/common/lib
- все эти DLL находятся в
WEB-INF/lib
веб-приложения
Ответы
Ответ 1
Чтобы работать System.loadLibrary()
, библиотека (в Windows, DLL) должна находиться в каталоге где-то на вашем PATH
или по пути, указанному в системном свойстве java.library.path
(чтобы вы могли запускать Java например java -Djava.library.path=/path/to/dir
).
Кроме того, для loadLibrary()
вы указываете базовое имя библиотеки, без .dll
в конце. Итак, для /path/to/something.dll
вы просто используете System.loadLibrary("something")
.
Вам также нужно посмотреть на точный UnsatisfiedLinkError
, который вы получаете. Если он говорит что-то вроде:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no foo in java.library.path
то он не может найти библиотеку foo (foo.dll) в PATH
или java.library.path
. Если он говорит что-то вроде:
Exception in thread "main" java.lang.UnsatisfiedLinkError: com.example.program.ClassName.foo()V
то что-то не так с самой библиотекой в том смысле, что Java не может сопоставить собственную Java-функцию в вашем приложении с ее фактическим родным экземпляром.
Для начала, я бы поместил несколько журналов вокруг вашего вызова System.loadLibrary()
, чтобы убедиться, что это выполняется должным образом. Если он генерирует исключение или не находится в кодовом пути, который фактически выполняется, тогда вы всегда получите последний тип UnsatisfiedLinkError
, описанный выше.
В качестве побочного элемента большинство людей помещают свои вызовы loadLibrary()
в статический блок инициализатора в классе с помощью собственных методов, чтобы гарантировать, что он выполняется только один раз:
class Foo {
static {
System.loadLibrary('foo');
}
public Foo() {
}
}
Ответ 2
Изменение переменной "java.library.path" во время выполнения недостаточно, потому что JVM читает только один раз. Вы должны reset это как:
System.setProperty("java.library.path", path);
//set sys_paths to null
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
Пожалуйста, возьмите добычу по адресу: Изменение пути библиотеки Java в Runtime.
Ответ 3
Оригинальный ответ Адама Баткина приведет вас к решению, но если вы повторно развернете свой webapp (без перезапуска вашего веб-контейнера), вы должны столкнуться с следующей ошибкой:
java.lang.UnsatisfiedLinkError: Native Library "foo" already loaded in another classloader
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1715)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1646)
at java.lang.Runtime.load0(Runtime.java:787)
at java.lang.System.load(System.java:1022)
Это происходит потому, что ClassLoader, который первоначально загрузил вашу DLL, по-прежнему ссылается на эту DLL. Тем не менее, ваш webapp теперь работает с новым ClassLoader и потому, что работает тот же JVM, и JVM не позволяет использовать 2 ссылки на одну и ту же DLL, вы не можете ее перезагрузить. Таким образом, ваш webapp не может получить доступ к существующей DLL и не может загрузить новую. Итак... ты застрял.
Документация Tomcat ClassLoader описывает, почему ваш перезагруженный webapp работает в новом изолированном ClassLoader и как вы можете обойти это ограничение (на очень высоком уровне).
Решение состоит в том, чтобы немного расширить решение Адама Баткина:
package awesome;
public class Foo {
static {
System.loadLibrary('foo');
}
// required to work with JDK 6 and JDK 7
public static void main(String[] args) {
}
}
Затем поместите банку, содержащую JUST этот скомпилированный класс в папку TOMCAT_HOME/lib.
Теперь, в вашем webapp, вам просто нужно заставить Tomcat ссылаться на этот класс, что можно сделать так просто:
Class.forName("awesome.Foo");
Теперь ваша DLL должна быть загружена в общий загрузчик классов, и на нее можно ссылаться из вашего webapp даже после перераспределения.
Имеют смысл?
Рабочую копию справки можно найти в коде google, static-dll-bootstrapper.
Ответ 4
Вы можете использовать System.load()
, чтобы предоставить абсолютный путь, который вы хотите, а не файл в стандартной папке библиотеки для соответствующей ОС.
Если вы хотите, чтобы существующие приложения уже существовали, используйте System.loadLibrary(String filename)
. Если вы хотите предоставить свой собственный, вы, вероятно, лучше с load().
Вы также должны правильно использовать loadLibrary
с java.library.path
. См. ClassLoader.java
для источника реализации, показывающего оба проверенных пути (OpenJDK)
Ответ 5
В случае, когда проблема заключается в том, что System.loadLibrary не может найти соответствующую DLL, одно распространенное заблуждение (усиленное сообщением об ошибке Java) заключается в том, что системным свойством java.library.path является ответ. Если вы установите системное свойство java.library.path в каталог, где находится ваша DLL, то System.loadLibrary действительно найдет вашу DLL. Однако, если ваша DLL, в свою очередь, зависит от других DLL, как это часто бывает, тогда java.library.path не может помочь, потому что загрузка зависимых DLL полностью управляется операционной системой, которая ничего не знает о java.library. дорожка. Таким образом, почти всегда лучше обойти java.library.path и просто добавить ваш каталог DLL в LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS) или Путь (Windows) до запуска JVM.
(Примечание. Я использую термин "DLL" в общем смысле DLL или разделяемой библиотеки.)
Ответ 6
Если вам нужно загрузить файл, относящийся к какой-либо директории, где вы уже находитесь (например, в текущем каталоге), здесь простое решение:
File f;
if (System.getProperty("sun.arch.data.model").equals("32")) {
// 32-bit JVM
f = new File("mylibfile32.so");
} else {
// 64-bit JVM
f = new File("mylibfile64.so");
}
System.load(f.getAbsolutePath());
Ответ 7
Для тех, кто ищет java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path
Я столкнулся с тем же исключением; Я пробовал все и важные вещи, чтобы заставить его работать:
- Правильная версия pdf lib.jar(в моем случае это была неправильная версия jar, хранящаяся во время выполнения сервера)
- Создайте папку и сохраните в ней банку pdflib и добавьте папку в свою переменную PATH
Он работал с tomcat 6.
Ответ 8
Бедняжка! провел целый день за этим. Записывая его здесь, если какой-либо орган реплицирует эту проблему.
Я пытался загрузить, как предложил Адам, но затем попался с AMD64 против исключения IA 32. Если в любом случае после работы в соответствии с прохождением Adam (без сомнения, лучшего выбора) попробуйте иметь 64-разрядную версию последней версии jre. Убедитесь, что ваш JRE AND JDK 64 бит, и вы правильно добавили его в свой путь к классам.
Мой рабочий пример здесь: неудовлетворенная ошибка ссылки
Ответ 9
-
Если вы считаете, что вы добавили путь к собственной lib в %PATH%
, попробуйте выполнить тестирование с:
System.out.println(System.getProperty("java.library.path"))
Это должно показать вам на самом деле, если ваша DLL на %PATH%
- Перезапустите IDE Idea, которая, кажется, работает для меня после того, как я настроил переменную env, добавив ее в
%PATH%
Ответ 10
В Windows я обнаружил, что когда я загружал заполнение (вызовы jd2xsx.dll и ftd2xx.dll) в папку windowws/system32, это устранило проблемы. У меня тогда возникла проблема с моим новым fd2xx.dll, связанным с параметрами, поэтому мне пришлось загрузить более старую версию этой DLL. Мне придется это сделать позже.
Примечание: jd2xsx.dll вызывает ftd2xx.dll, поэтому установка пути для jd2xx.dll может не работать.
Ответ 11
Я использую Mac OS X Yosemite и Netbeans 8.02, у меня такая же ошибка, и простое решение, которое я нашел, похоже на выше, это полезно, когда вам нужно включить в проект собственную библиотеку. Итак, сделайте следующее для Netbeans:
1.- Right click on the Project
2.- Properties
3.- Click on RUN
4.- VM Options: java -Djava.library.path="your_path"
5.- for example in my case: java -Djava.library.path=</Users/Lexynux/NetBeansProjects/NAO/libs>
6.- Ok
Я надеюсь, что это может быть полезно для кого-то.
Ссылка, в которой я нашел решение, находится здесь:
java.library.path - что это такое и как использовать
Ответ 12
У меня была такая же проблема и ошибка была из-за переименования dll. Может случиться так, что имя библиотеки также записано где-то внутри DLL. Когда я вернул его первоначальное имя, я смог загрузить с помощью System.loadLibrary
Ответ 13
This is My java.library.path:
java.library.path = C:\Program Files\Java\jdk1.7.0_51\bin
C:\WINDOWS\Sun\Java\bin
C:\WINDOWS\system32
C:\WINDOWS
C:\WINDOWS\system32
C:\Program Files\I.R.I.S. SA\iDRS_15_2_for_Win64_15_2_11_1717\lib\idrskr
.lib
C:\Program Files\I.R.I.S. SA\iDRS_15_2_for_Win64_15_2_11_1717\bin\iDRMSG
idgeDll.dll
C:\Program Files\I.R.I.S. SA\iDRS_15_2_for_Win64_15_2_11_1717\bin\iDRMSG
aderDll.dll
C:\Program Files\Java\jdk1.7.0_51\bin
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib
C:\WINDOWS\System32\Wbem
C:\WINDOWS\System32\WindowsPowerShell\v1.0
C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\
C:\Program Files\Microsoft SQL Server\100\DTS\Binn
Still rror comes:
infile >> D:\pdf_upload\pre_idrs15_win_temporary_license_activation_tutorial.pdf
outFile >> D:\pdf_upload\processed\pre_idrs15_win_temporary_license_activation_tutorial.txt
Hello : This is java library path:(NICKRJ) C:\Program Files\Java\jdk1.7.0_51\bin;C:\WINDOWS\Sun\Java\bin;C:\WINDOWS\system32;C:\WINDOWS;C:/Program Files/Java/jdk1.7.0_51/jre/bin/server;C:/Program Files/Java/jdk1.7.0_51/jre/bin;C:/Program Files/Java/jdk1.7.0_51/jre/lib/amd64;C:\WINDOWS\system32;C:\Program Files\I.R.I.S. SA\iDRS_15_2_for_Win64_15_2_11_1717\lib\idrskrn15.lib;C:\Program Files\I.R.I.S. SA\iDRS_15_2_for_Win64_15_2_11_1717\bin\iDRMSGEBridgeDll.dll;C:\Program Files\I.R.I.S. SA\iDRS_15_2_for_Win64_15_2_11_1717\bin\iDRMSGEReaderDll.dll;C:\Program Files\Java\jdk1.7.0_51\bin;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\lib;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn;D:\WorkSet\New folder\eclipse_kepler\eclipse;;.
Exception in thread "main" java.lang.UnsatisfiedLinkError: no iDRMSGEBridgeDll in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
at java.lang.Runtime.loadLibrary0(Runtime.java:849)
at java.lang.System.loadLibrary(System.java:1088)
at com.bi.iDRMSGEBridgeDll.callOcr(iDRMSGEBridgeDll.java:78)
at com.bi.iDRMSGEBridgeDll.main(iDRMSGEBridgeDll.java:15)
Here is my Java JNI class:
package com.bi;
import org.omg.PortableInterceptor.SYSTEM_EXCEPTION;
public class iDRMSGEBridgeDll
{
public native int iDRMSGEDll_Initialize(String strPropertiesFileName);
public native int iDRMSGEDll_VerifyLicense();
public native int iDRMSGEDll_ConvertFile(String strSourceFileName, String srcOutputFileName, String formatType);
public native int iDRMSGEDll_Finalize();
public static void main(String[] args)
{
//iDRMSGEBridgeDll.callOcr("bgimage.jpg","jpg","","d:\\","d:\\","4");
iDRMSGEBridgeDll.callOcr("pre_idrs15_win_temporary_license_activation_tutorial.pdf","pdf","","D:\\pdf_upload","D:\\pdf_upload\\processed","4");
/* System.loadLibrary("iDRMSGEBridgeDll");
iDRMSGEBridgeDll obj = new iDRMSGEBridgeDll();
if ( obj.iDRMSGEDll_Initialize("D:\\iris\\iDRSGEDll.properties") != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_Initialize success.");
if ( obj.iDRMSGEDll_VerifyLicense() != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_VerifyLicense success.");
if (obj.iDRMSGEDll_ConvertFile("E:\\UI changes File_by Shakti\\PDF\\S14-005_FRAMEWORK_AGREEMENT_FOR_ENGINE_MAINTENANCE_SERVICES_EASYJET[1].pdf",
"E:\\SK_Converted_Files\\MVP_CONTRACTS\\Southwest CFM56-7\\S14-005_FRAMEWORK_AGREEMENT_FOR_ENGINE_MAINTENANCE_SERVICES_EASYJET[1]\\S14-005_FRAMEWORK_AGREEMENT_FOR_ENGINE_MAINTENANCE_SERVICES_EASYJET[1].txt", "4" ) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 1 success.");
/*if (obj.iDRMSGEDll_ConvertFile("C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_200dpi.pdf",
"C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_200dpi.out", 4) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 2 success.");
if (obj.iDRMSGEDll_ConvertFile("C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_300dpi.pdf",
"C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_300dpi.out", 4) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 3 success.");
if (obj.iDRMSGEDll_ConvertFile("C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan2_300dpi.pdf",
"C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan2_300dpi.out", 4) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 4 success.");
obj.iDRMSGEDll_Finalize();
System.out.println("iDRMSGEDll_Finalize success.");
return;*/
}
public static String callOcr(String inputFile, String docType, String engineType, String filePath,String outputFolder,String type) throws RuntimeException
{
String message = "";
String formatType = type;
String inFile = filePath +"\\" +inputFile;
String outFile="";
if(type.equals("4"))
outFile = outputFolder +"\\"+inputFile.substring(0,inputFile.lastIndexOf("."))+".txt";
else if(type.equals("6"))
outFile = outputFolder +"\\"+inputFile.substring(0,inputFile.lastIndexOf("."))+".rtf";
else if(type.equals("9"))
outFile = outputFolder +"\\"+inputFile.substring(0,inputFile.lastIndexOf("."))+".pdf";
else
outFile = outputFolder +"\\"+inputFile.substring(0,inputFile.lastIndexOf("."))+".csv";
System.out.println("infile >> "+inFile);
System.out.println("outFile >> "+outFile);
System.out.println("Hello : This is java library path:(NICKRJ) " +System.getProperty("java.library.path"));
System.loadLibrary("iDRMSGEBridgeDll");
//System.load("C:\\Program Files (x86)\\I.R.I.S. SA\\iDRS_15_2_for_Win64_15_2_11_1717\bin\\iDRMSGEBridgeDll.dll");
//Runtime.getRuntime().loadLibrary("iDRMSGEBridgeDll");
iDRMSGEBridgeDll obj = new iDRMSGEBridgeDll();
try
{
if ( obj.iDRMSGEDll_Initialize("D:\\IRIS\\iDRSGEDll.properties") != 0 ) {
obj.iDRMSGEDll_Finalize();
// return ;
}
System.out.println("iDRMSGEDll_Initialize success.");
if ( obj.iDRMSGEDll_VerifyLicense() != 0 ) {
obj.iDRMSGEDll_Finalize();
// return;
}
System.out.println("iDRMSGEDll_VerifyLicense success.");
// formatType= JOptionPane.showInputDialog("Please input mark format type: ");
if (formatType!=null && formatType.equals("4")) {
obj.iDRMSGEDll_ConvertFile(inFile,
outFile, "4" );
obj.iDRMSGEDll_Finalize();
// return;
}
else if(formatType!=null && formatType.equals("6")) {
obj.iDRMSGEDll_ConvertFile(inFile,
outFile, "6" );
obj.iDRMSGEDll_Finalize();
// return;
}
else if(formatType!=null && formatType.equals("7")) {
obj.iDRMSGEDll_ConvertFile(inFile,
outFile, "7" );
obj.iDRMSGEDll_Finalize();
// return;
}
else if(formatType!=null && formatType.equals("9")) {
obj.iDRMSGEDll_ConvertFile(inFile,
outFile, "9" );
obj.iDRMSGEDll_Finalize();
// return;
}
else
{
message= "iDRMSGEDll_VerifyLicense failure";
}
System.out.println("iDRMSGEDll_ConvertFile 1 success.");
/*if (obj.iDRMSGEDll_ConvertFile("C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_200dpi.pdf",
"C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_200dpi.out", 4) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 2 success.");
if (obj.iDRMSGEDll_ConvertFile("C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_300dpi.pdf",
"C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan1_300dpi.out", 4) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 3 success.");
if (obj.iDRMSGEDll_ConvertFile("C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan2_300dpi.pdf",
"C:\\Software\\iDRS_15_1_7_2304\\sample_pdfs\\scan2_300dpi.out", 4) != 0 ) {
obj.iDRMSGEDll_Finalize();
return;
}
System.out.println("iDRMSGEDll_ConvertFile 4 success.");*/
obj.iDRMSGEDll_Finalize();
System.out.println("iDRMSGEDll_Finalize success.");
if(message.length()==0)
{
message = "success";
}
}
catch(Exception e)
{
e.printStackTrace();
message = e.getMessage();
}
return message;
}
}