[java] java.lang.UnsatisfiedLinkError java.library.path에 *****. dll 없음

웹 애플리케이션에서 사용자 지정 dll 파일을로드하려면 어떻게해야합니까? 나는 다음을 시도했다 :

  • system32폴더에 필요한 모든 dll을 복사하고 Servlet생성자 에 그중 하나를로드하려고했습니다.System.loadLibrary
  • 필요한 dll을 tomcat_home/shared/libtomcat_home/common/lib

이 모든 dll은 WEB-INF/lib웹 응용 프로그램에 있습니다.



답변

위해서는 System.loadLibrary()일에, (윈도우, DLL을에) 라이브러리는 당신의 디렉토리의 어딘가에 있어야합니다 PATH 에 나열된 경로에 java.library.path(당신이 좋아하는 자바를 실행할 수 있도록 시스템 프로퍼티 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)를 찾을 수 없습니다 . 다음과 같은 경우 :PATHjava.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 라이브러리 경로 변경 .


답변

Adam Batkin의 원래 답변은 솔루션을 제공하지만 웹 컨테이너를 다시 시작하지 않고 웹 앱을 다시 배포하면 다음 오류가 발생해야합니다.

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)

이것은 원래 DLL을로드 한 ClassLoader가 여전히이 DLL을 참조하기 때문에 발생합니다. 그러나 웹앱은 이제 새로운 ClassLoader로 실행되고 있으며 동일한 JVM이 실행 중이고 JVM이 동일한 DLL에 대한 2 개의 참조를 허용하지 않기 때문에 다시로드 할 수 없습니다 . 따라서 웹앱은 기존 DLL에 액세스 할 수 없으며 새 DLL을로드 할 수 없습니다. 그래서 …. 당신은 갇혀 있습니다.

Tomcat의 ClassLoader 문서 는 새로 고침 된 웹앱이 새로운 격리 된 ClassLoader에서 실행되는 이유와이 제한을 해결하는 방법 (매우 높은 수준에서)을 설명합니다.

해결책은 Adam Batkin의 솔루션을 약간 확장하는 것입니다.

   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를 TOMCAT_HOME / lib 폴더에 넣습니다.

이제 웹앱 내에서 Tomcat이이 클래스를 참조하도록 강제하면됩니다.이 작업은 다음과 같이 간단하게 수행 할 수 있습니다.

  Class.forName("awesome.Foo");

이제 DLL은 공통 클래스 로더에로드되어야하며 재배포 후에도 웹앱에서 참조 할 수 있습니다.

말이 되나?

작업 참조 사본은 Google 코드 static-dll-bootstrapper 에서 찾을 수 있습니다 .


답변

System.load()각 OS의 표준 라이브러리 폴더에있는 파일이 아닌 원하는 절대 경로를 제공하는 데 사용할 수 있습니다 .

이미 존재하는 기본 애플리케이션을 원하는 경우 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를 전혀 모르는 운영 체제에 의해 전적으로 관리되기 때문입니다. 통로. 따라서 JVM을 시작하기 전에 java.library.path를 우회하고 DLL의 디렉토리를 LD_LIBRARY_PATH (Linux), DYLD_LIBRARY_PATH (MacOS) 또는 Path (Windows)에 추가하는 것이 거의 항상 좋습니다.

(참고 : 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 변수에 폴더를 추가하십시오.

바람둥이 6에서 작동했습니다.