해결lang.UnsatisfiedLinkError: Native Library .dll already loaded in another

1510 단어 library
필자는 얼마 전에 두 항목에서 같은 applet을 사용한 다음에 applet에서 dll조작(jni 또는 jna 사용)을 호출한 다음에 클라이언트에서 호출하는 상황을 만났다.실제 방문 과정은 다음과 같다. 먼저 프로젝트 A의 한 인터페이스를 방문했는데 인터페이스에서 appletA를 호출했다. 이어서 브라우저를 닫지 않고 프로젝트 B의 인터페이스를 직접 방문했고 인터페이스에서 appletB를 호출했다.애플릿A와 애플릿B는 사실상 같은 애플릿이다. 단지 이 애플릿은 두 항목에 사용되고 두 항목은 모두 직접 방문한다.이 때 애플릿 B를 방문할 때 오류가 발생합니다.
1xxx NOT loaded java.lang.UnsatisfiedLinkError : Native Library XXX.dll already loaded in another classloaderappletB에서 appletA에 접근하면 appletA에 접근할 때도 같은 오류가 발생합니다.한 탭에서 여러 개의 applet이 실제적으로 같은 jvm에서 실행되고, 단지 applet을 불러올 때 다른classLoader를 사용했기 때문이다.따라서 appletA가 먼저 실행되든 appletB가 먼저 실행되든 최종 상황은 의존하는 dll이 같은 jvm에 불러오면 이상의 오류가 발생할 수 있습니다.
구글을 진행한 후에 많은 개발자들이 같은 문제에 부딪혔다. 어떤 것은 같은javaEE 용기, 예를 들어 (weblogic, jboss) 중부에 두 개의 jni 호출 프로젝트를 방문해야 하기 때문이다. 어떤 것은 필자와 같은 경험이다.마지막 결론은 한 jvm에서 dll을 두 번 불러오는 것을 허용하지 않는다는 것이다.따라서 뒤에 있는 jni를 호출할 때 같은 dll을 다시 불러오려고 시도하면 위의 오류를 보고합니다.이 오류로 인해 대응하는 자바 클래스는 초기화될 수 없기 때문에 해당 항목이나 applet은 시작할 수 없습니다.
이 문제를 해결하는 것은 사실 매우 간단하다. jni에 접근한 코드를 단독으로 추출하여 프로젝트 자체의classLoader를 직접 불러오지 않고 시스템Loader에서 불러오면 된다.한 가지 방법은 이 부분의 코드를 단독으로jar로 봉하여 자바의 시스템Loader가 불러올 수 있는 곳, 예를 들어lib/ext 디렉터리에 넣는 것이다.그리고 프로젝트에서 이 코드를 호출합니다.dll에 접근하는 코드는 시스템로드러에서 불러오기 때문에 여러 항목이 같은 dll에 동시에 접근할 때 다시 불러오는 것을 피할 수 있습니다.두 번째 항목이 접근할 때 찾은 클래스는 시스템로드러에 의해 불러왔기 때문에 프로젝트 자체의classLoader는 이 클래스를 다시 불러오지 않습니다.
비교해 보면 원래의 appletA, appletB는 수정된 후에 이러한 구조가 되었다. appletA, appletB, 그리고 jniAccess.jar, 여기서 jniAccess.jar는 jre의lib 디렉터리의 ext 디렉터리에 있습니다.이렇게 하면 애플릿을 다시 방문하면 문제가 없습니다.

좋은 웹페이지 즐겨찾기