java.lang.UnsatisfiedLinkError нет *****.dll в java.library.path

Как я могу загрузить пользовательский файл DLL в моем веб-приложении? Я пробовал следующие способы, но это не удалось.

  • скопировал все необходимые библиотеки в system32 папку и попытался загрузить один из них в Servlet конструктор System.loadLibrary
  • Скопированы необходимые библиотеки в tomcat_home/shared/lib а также tomcat_home/common/lib
  • все эти библиотеки находятся в WEB-INF/lib веб-приложения

16 ответов

Решение

Для того чтобы 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() {
    }

}

Изменение переменной 'java.library.path' во время выполнения недостаточно, потому что JVM читает только один раз. Вы должны сбросить его как:

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 во время выполнения.

Исходный ответ Адама Баткина приведет вас к решению, но если вы повторно развернете свое веб-приложение (без перезапуска веб-контейнера), вы должны столкнуться со следующей ошибкой:

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. Однако ваше веб-приложение теперь работает с новым ClassLoader, и поскольку та же JVM работает, а JVM не допускает двух ссылок на одну и ту же DLL, вы не можете перезагрузить ее. Таким образом, ваше веб-приложение не может получить доступ к существующей DLL и не может загрузить новую. Итак... ты застрял.

Документация Tomcat по ClassLoader описывает, почему ваше перезагруженное веб-приложение работает в новом изолированном 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) {
        }

    }

Затем поместите jar, содержащий JUST этот скомпилированный класс, в папку TOMCAT_HOME/lib.

Теперь в вашем веб-приложении вам просто нужно заставить Tomcat ссылаться на этот класс, что можно сделать так просто:

  Class.forName("awesome.Foo");

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

Есть смысл?

Работающую справочную копию можно найти в коде Google, http://code.google.com/p/static-dll-bootstrapper/.

Ты можешь использовать System.load() предоставить абсолютный путь, который вам нужен, а не файл в стандартной папке библиотеки для соответствующей ОС.

Если вы хотите, чтобы собственные приложения уже существовали, используйте System.loadLibrary(String filename), Если вы хотите предоставить свой собственный, вы, вероятно, лучше с load().

Вы также должны быть в состоянии использовать loadLibrary с java.library.path установить правильно. Увидеть ClassLoader.java для источника реализации, показывающего оба проверяемых пути (OpenJDK)

В случае, когда проблема состоит в том, что 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) или Path (Windows) до запуска JVM.

(Примечание: я использую термин "DLL" в общем смысле DLL или разделяемой библиотеки.)

Если вам нужно загрузить файл, относящийся к некоторому каталогу, в котором вы уже находитесь (как в текущем каталоге), вот простое решение:

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());

Для тех, кто ищет java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

Я столкнулся с тем же исключением; Я перепробовал все и важные вещи, чтобы он работал:

  1. Правильная версия pdf lib.jar (в моем случае неверная версия jar сохранялась во время работы сервера)
  2. Создайте папку и сохраните в ней pdflib jar и добавьте папку в переменную PATH

Это работало с Tomcat 6.

Проблема для меня заключалась в том, чтобы назвать:

Имя библиотеки должно начинаться с "lib...", например libnative.dll.

Итак, вы можете подумать, что вам нужно загрузить «libnative»: System.loadLibrary("libnative")

Но на самом деле вам нужно загрузить «родной»: System.loadLibrary("native")

  1. Если вы считаете, что вы добавили путь к собственной lib в%PATH%, проверьте себя еще раз:

    System.out.println (System.getProperty ("java.library.path"))

Это должно показать вам на самом деле, если ваша DLL на% PATH%

  1. Перезапустите IDE Идея, да, мне показалось, что она работает после того, как я настроил переменную env, добавив ее в% PATH%

Я использую 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 - что это такое и как использовать

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

Я пытался загрузить, как предложил Адам, но потом попался с исключением AMD64 против IA 32. Если в любом случае после работы в соответствии с прохождением Адама (без сомнения, лучший выбор), попробуйте 64-битную версию последней jre. Убедитесь, что ваш JRE и JDK являются 64-битными, и вы правильно добавили его в ваш путь к классам.

Вот мой рабочий пример: ошибка неудовлетворительной ссылки

Просто напишите java -XshowSettings:properties в командной строке в Windows, а затем вставьте все файлы по пути, указанному в java.library.path.

Для Windows я обнаружил, что, когда я загрузил файлы (jd2xsx.dll вызывает & ftd2xx.dll) в папку windowws/system32, это решило проблемы. Затем у меня возникла проблема с моим новым fd2xx.dll, связанным с параметрами, поэтому мне пришлось загружать более старую версию этой библиотеки DLL. Мне придется выяснить это позже.

Примечание: jd2xsx.dll вызывает ftd2xx.dll, поэтому установка пути для jd2xx.dll может не сработать.

Во-первых, вам нужно убедиться, что каталог вашей собственной библиотеки находится на java.library.path. Посмотрите, как это сделать здесь. Тогда вы можете позвонить System.loadLibrary(nativeLibraryNameWithoutExtension) - убедитесь, что в имени вашей библиотеки не указано расширение файла.

У меня была такая же проблема и ошибка была из-за переименования dll. Может случиться так, что имя библиотеки также записано где-то внутри DLL. Когда я вернул его первоначальное имя, я смог загрузить с помощью System.loadLibrary

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;





    }


}
Другие вопросы по тегам