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


92

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

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

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

답변:


156

위해서는 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() {
    }

}

1
모든 dll을 System32에 넣고 System.loadLibrary ( "something")을 사용하여 작동했습니다. 이전에 System.loadLibrary ( "something.dll")을 수행했습니다. WEB-INF에서 모든 dll을로드 할 수없는 이유는 무엇입니까? 기본적으로 모든 항아리를로드한다고 생각합니다. System32 대신 WEB-INF에서 직접 이러한 dll을로드하려면 어떻게해야합니까
/java.library.path

2
설명을 위해 "bla.dll"대신 "bla"를 사용하면 +1- loadLibrary()잘못하고있는 일에 대한 단서가 없을 때 매우 유용합니다.
MarnixKlooster ReinstateMonica

21
내 시스템 (Linux 및 java7)에서 lib접두사 가 필요 합니다. 그래서 System.loadLibrary("foo")필요합니다 libfoo.so.
kristianlm 2013 년

2
감사. Windows 용 "PATH"를 업데이트하여 * .so 파일이있는 폴더를 포함하도록했습니다.
user613114 2014

나는 OSX blah.jnilib와 리눅스가 필요하다고 맹세 할 수 있었다 libblah.so. 음, 2 시간 후, 수많은 시도 끝에 OSX에도 lib접두어 가 필요하다는 결론에 도달했습니다
Jovan Perovic

15

'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 라이브러리 경로 변경 .


10

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 에서 찾을 수 있습니다 .


1
이 답변은 응용 프로그램 서버에 탁월하며이 질문에 낭비되므로 자체 질문이 있어야합니다.
JoshDM

8

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

이미 존재하는 기본 애플리케이션을 원하는 경우 System.loadLibrary(String filename). 자신의 것을 제공하려면 load ()를 사용하는 것이 좋습니다.

당신은 또한 사용할 수 있어야합니다 loadLibrary으로 java.library.path올바르게 설정. ClassLoader.java확인되는 두 경로를 모두 보여주는 구현 소스를 참조하십시오 (OpenJDK).


감사. 부하를 사용하는 것은 실제로 훨씬 쉽고 직관적 인 IMHO입니다. 아무리 내가 무슨 짓을 일에를 LoadLibrary 얻을 수 없습니다 ...
Plankalkül

2
이 솔루션은 자체 네이티브 라이브러리를로드하는 라이브러리에는 작동하지 않습니다.
Justin Skiles 2014

7

문제가 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"이라는 용어를 사용하고 있습니다.)


5

현재 디렉토리와 같이 이미있는 일부 디렉토리에 상대적인 파일을로드해야하는 경우 다음과 같은 쉬운 해결책이 있습니다.

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

4

찾는 분들을 위해 java.lang.UnsatisfiedLinkError: no pdf_java in java.library.path

나는 같은 예외에 직면했다. 나는 그것을 작동시키기 위해 모든 것을 시도했고 중요한 것은 다음과 같습니다.

  1. 올바른 버전의 pdf lib.jar (제 경우에는 서버 런타임에 잘못된 버전 jar가 보관되었습니다)
  2. 폴더를 만들고 그 안에 pdflib jar를 유지하고 PATH 변수에 폴더를 추가하십시오.

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


3
  1. 에 native lib 경로를 추가했다고 생각되면 다음을 사용하여 %PATH%테스트 해보세요.

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

dll이 켜져 있는지 실제로 보여줄 것입니다. %PATH%

  1. env 변수를 설정 한 후 작동하는 것으로 보이는 IDE Idea를 다시 시작하십시오. %PATH%

2

가난한 날 ! 하루 종일이 문제를 반복하는 사람이 있으면 여기에 적어 두었습니다.

Adam이 제안한대로로드하려고했지만 AMD64 대 IA 32 예외가 발생했습니다 .Adam 's (의심 할 여지없이 최고의 선택) 연습에 따라 작업 한 후 어떤 경우에도 최신 jre의 64 비트 버전을 사용해보십시오. JRE 및 JDK는 64 비트이며 클래스 경로에 올바르게 추가했습니다.

내 작업 예제는 여기에 있습니다 : unstatisfied link error


0

Windows의 경우 filles (jd2xsx.dll 호출 및 ftd2xx.dll)를 windowws / system32 폴더에로드하면 문제가 해결된다는 것을 알았습니다. 그런 다음 새 fd2xx.dll이 매개 변수와 관련하여 문제가 발생 하여이 dll의 이전 버전을로드해야했습니다. 나중에이 문제를 해결해야합니다.

참고 : jd2xsx.dll은 ftd2xx.dll을 호출하므로 jd2xx.dll의 경로 설정 만 작동하지 않을 수 있습니다.


0

저는 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 – 정의 및 사용 방법


라이브러리 경로가이 라인의 경로에서 약간의 간격을 포함하는 경우 안녕 알렉스, 여기 질문은 문제가있다VM Options: java -Djava.library.path="your_path"
록쉬 펜디 교수

Mmm 작년에 Java로 작업하지 않았지만 충돌이 나타날 수 있으므로 파일 경로에 빈 공간을 추가하지 않는 것이 좋습니다 .
alexventuraio

0

나는 같은 문제가 있었고 오류는 dll의 이름 변경으로 인한 것입니다. 라이브러리 이름도 dll 내부에 기록 될 수 있습니다. 원래 이름을 되 돌리면 다음을 사용하여로드 할 수있었습니다.System.loadLibrary


0

Windows의 명령 줄에 java -XshowSettings : properties를 작성한 다음 java.library.path에 표시된 경로에 모든 파일을 붙여 넣는 것은 간단합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.