【发布时间】:2020-01-06 05:00:23
【问题描述】:
我正在尝试在 RHEL 中编译和运行以下 JNI Java 文件:
package com.isprint.am.util.hsm;
public class LunaMDUtil {
//bunch of constants
public native int MD_Initialize();
//...and a bunch of other native methods
static {
System.loadLibrary("ethsm");
System.loadLibrary("LunaMDUtil");
}
public static void main(String[] args) {
// some test code code
}
}
(我省略了代码,因为我认为它与问题无关。)
在我的开发文件夹中,我有以下文件:
// files used to build libLunaMDUtil.so
com_isprint_am_util_hsm_LunaMDUtil.c
com_isprint_am_util_hsm_LunaMDUtil.h
ethsm.lib
libLunaMDUtil.so
LunaMDUtil.java (i.e the above Java source code file)
要构建libLunaMDUtil.so,我运行以下命令:
gcc -fPIC -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -shared -o libLunaMDUtil.so com_isprint_am_util_hsm_LunaMDUtil.c
这里没有错误。接下来我编译我的LunaMDUtil.java:
javac -cp . LunaMDUtil.java
这里没有错误。这里的最后一步是我开始遇到问题的地方。
运行java -Xdiag -cp . LunaMDUtil 给我这个错误:
Error: Could not find or load main class LunaMDUtil
java.lang.NoClassDefFoundError: LunaMDUtil (wrong name: com/isprint/am/util/hsm/LunaMDUtil)
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:763)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:468)
at java.net.URLClassLoader.access$100(URLClassLoader.java:74)
at java.net.URLClassLoader$1.run(URLClassLoader.java:369)
at java.net.URLClassLoader$1.run(URLClassLoader.java:363)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:362)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
接下来,我运行 java -Xdiag -cp . com.isprint.am.util.hsm.LunaMDUtil 并收到此错误:
Error: Could not find or load main class com.isprint.am.util.hsm.LunaMDUtil
java.lang.ClassNotFoundException: com.isprint.am.util.hsm.LunaMDUtil
at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)
我将我的 .class 文件移动到文件夹 ./com/isprint/am/util/hsm(在包名之后),这次我得到了:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no ethsm in java.library.path
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
at java.lang.Runtime.loadLibrary0(Runtime.java:870)
at java.lang.System.loadLibrary(System.java:1122)
at com.isprint.am.util.hsm.LunaMDUtil.<clinit>(LunaMDUtil.java:67)
此时我的手开始变得僵硬,因为ethsm.lib 是来自外部方的库,我希望尽可能避免重命名它。另外,如果可能,我想避免更改源代码。 (当然,如果唯一的解决方案涉及进行这些更改,那么至少我有一些理由。)
我应该进行哪些更改才能让LunaMDUtil.java 中的测试代码运行?
【问题讨论】:
-
ethsm真的是 JNI 库吗?或者只是LunaMDUtil依赖的东西?如果是后者,您根本不应该尝试加载它。 -
@user207421
ethsm不是 JNI 库,而是包含我的 C 源文件调用的函数 -
没错,所以不要尝试将其作为 JNI 库加载。如果它是 .lib 你的 C 代码已经静态链接到它;否则,如果它是 .so 您的 C 代码已经动态链接到它。你不需要再做任何事情了。
-
@user207421 - “如果它是 .so 你的 C 代码已经动态链接到它。你不需要再做任何事情了。” - 恐怕这并不完全正确。这取决于系统,但链接到
.so是不够的。您必须确保您链接到的.so位于LD_LIBRARY_PATH上,或者您链接到-rpath。否则,系统将看不到该库。java.library.path仅对使用loadLibrary加载的库有效,不适用于该库依赖的其他库。在 Windows 中,此库必须位于PATH。 -
@Oo.oO 请注意上下文。就链接和加载而言,这已经足够了。当它不是时,您不必尝试将它作为 JNI 库加载。 当然 .so 必须在运行时出现,这是不言而喻的。关于
java.library.path,我一句话也没说。不要把话放在我嘴里。
标签: gcc java-native-interface javac rhel .so