java.lang.UnsatisfiedLinkError: org.thotheolh.jche.NativeBridge.loadPKCS11Module(Ljava/lang/String;)V

java.lang.UnsatisfiedLinkError: org.thotheolh.jche.NativeBridge.loadPKCS11Module(Ljava/lang/String;)V

我已经查看了 Whosebug 和其他搜索引擎中的 UnsatisfiedLinkError 帮助,但解决方案未能满足问题,因此我将在此处说明。

我正在尝试对 PKCS11 DLL 库进行 JNI 调用,但出现以下错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: org.thotheolh.jche.NativeBridge.loadPKCS11Module(Ljava/lang/String;)V
at org.thotheolh.jche.NativeBridge.loadPKCS11Module(Native Method)
at org.thotheolh.jche.NativeBridge.load(NativeBridge.java:40)
at org.thotheolh.jche.NativeBridge.<init>(NativeBridge.java:29)
at org.thotheolh.jche.exception.test.PKCS11GenericTest.main(PKCS11GenericTest.java:27)
Java Result: 1

我用来执行以下 'native' 调用的本机桥接代码段:

NativeBridge.java

public class NativeBridge {

private String pkcs11Module;
private String pkcs11JavaWrapper = "libJPKCS11";

public NativeBridge(String pkcs11Module) throws IOException, NoSuchFieldException {
    this.pkcs11Module = pkcs11Module;
    load();
}

public void load() throws IOException, NoSuchFieldException {
    System.loadLibrary(pkcs11JavaWrapper);
    loadPKCS11Module(pkcs11Module);
}

public synchronized native void loadPKCS11Module(String location) throws IOException;
}

javah 生成的头文件片段:

JCHE.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_thotheolh_jche_NativeBridge */

#ifndef _Included_org_thotheolh_jche_NativeBridge
#define _Included_org_thotheolh_jche_NativeBridge
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     org_thotheolh_jche_NativeBridge
 * Method:    loadPKCS11Module
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL Java_org_thotheolh_jche_NativeBridge_loadPKCS11Module
 (JNIEnv *, jobject, jstring);

#ifdef __cplusplus
}
#endif
#endif

C 文件片段:

JCHE.c

#include <jni.h>
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include "JCHE.h"

const char *pkcs11ModuleFileLoc;
HMODULE pkcs11;

JNIEXPORT void JNICALL Java_org_thotheolh_jche_NativeBridge_loadPKCS11Module
(JNIEnv *env, jobject obj, jstring location) {
    printf("inside native method\n");
    pkcs11ModuleFileLoc = (*env)->GetStringUTFChars(env, location, (jboolean *)0);
    printf("%s", pkcs11ModuleFileLoc);
    //pkcs11 = LoadLibraryA(pkcs11ModuleFileLoc);
    //printf("\nLoaded PKCS11 Lib");
}

我试图检查 Java 中加载的库,发现它们已经加载,但不知何故,尽管查看了许多其他可用的方法来尝试解决此问题,但我还是收到了描述的错误。

我试过了,但无法重现您的问题(但我使用了 Linux 并将 System.loadLibrary("libJPKCS11"); 更改为 System.loadLibrary("JPKCS11");,见下文,但我确定这不会导致您的问题,因为错误消息会有所不同)。

您收到的错误消息表示可以加载库,因此调用 System.loadLibrary().

没有问题

您确定 JCHE.objlibJPKCS11.dll 的成员吗,即 libJPKCS11.dll 是否正确链接,并且 JCHE.obj 是使用正确的标志构建的以创建 DLL ?对我来说,该消息看起来好像库已正确加载,但不包含函数 Java_org_thotheolh_jche_NativeBridge_loadPKCS11Module()。因此,您可能想要检查 libJPKCS11.dll 是否实际上是 "complete" 和 "up-to-date".

顺便说一下,您可以考虑删除 lib 前缀。 System.loadLibrary 负责前缀和后缀。您只会使用 System.loadLibrary("foo");。然后它在 POSIX 上加载 libfoo.so 并在 Windows 上加载 foo.dll。否则它会尝试在 POSIX 上加载 liblibfoo.so,这感觉很奇怪。

找到一个很老的 2012 Netbeans post 来解决问题。这是由于在制作 DLL 文件时缺少一些 GCC 编译器选项。

额外的 GCC 编译器选项:

-Wl,--export-all-symbols -Wl,--add-stdcall-alias 

参考: http://forums.netbeans.org/post-130319.html