Gcc 如何通过进行最小的更改来修复不满意的链接错误?
我正在尝试在RHEL中编译和运行以下JNI Java文件:Gcc 如何通过进行最小的更改来修复不满意的链接错误?,gcc,java-native-interface,javac,rhel,.so,Gcc,Java Native Interface,Javac,Rhel,.so,我正在尝试在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")
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
}
}
(我省略了代码,因为我认为它与问题无关。)
在我的dev文件夹中,我有以下文件:
// 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)
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)
接下来,我运行java-Xdiag-cp。com.isprint.am.util.hsm.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)
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)
线程“main”java.lang.UnsatifiedLinkError中出现异常:java.library.path中没有ethsm
位于java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
位于java.lang.Runtime.loadLibrary0(Runtime.java:870)
位于java.lang.System.loadLibrary(System.java:1122)
位于com.isprint.am.util.hsm.LunaMDUtil.(LunaMDUtil.java:67)
在这一点上,我的手开始被束缚,因为ethsm.lib
是一个来自外部方的库,如果可能的话,我希望避免重命名它。此外,如果可能的话,我希望避免对源代码进行更改。(当然,如果唯一的解决办法是做出这些改变,那么至少我有一些理由。)
我应该做哪些更改,以便运行
LunaMDUtil.java
中的测试代码?在您的代码中有以下静态代码
System.loadLibrary("ethsm");
它将加载libethsm.so
库。你必须确保它存在
您说ethsm.lib
来自外部开发人员。在这种情况下,请改用此函数
String path = "/this/is/path/to/your/ethsm/";
System.load(path + "ethsm.lib");
这样,库将按照load
中的指定从文件中加载
或者,您也可以始终创建符号链接:
ln -s ethsm.lib libethsm.so
但是,这只适用于共享库
链接到共享库而不在Java中加载它
如果您有共享库(例如:libethsm.so
),则始终可以将代码链接到此库
gcc -fPIC -I"$JAVA_HOME/include" \
-I"$JAVA_HOME/include/linux" \
-L$(ETHSM_LOCATION)
-lethsm
-shared -o libLunaMDUtil.so com_isprint_am_util_hsm_LunaMDUtil.c
但是,这将需要将此库放在LD\u LIBRARY\u路径上
或使用-rpath
链接
您可以在此处找到示例:
链接静态库而不在Java中加载它
如果您的库是一个静态库,那么在编译JNI
代码时,始终可以将它与代码链接起来
gcc -fPIC -I"$JAVA_HOME/include" \
-I"$JAVA_HOME/include/linux" \
-shared -o libLunaMDUtil.so \
com_isprint_am_util_hsm_LunaMDUtil.c \
ethsm.lib
您可以在此处找到示例:
将库直接放入共享库-如果您有源代码
如果您有源代码,您可以简单地将:JNI
和lib的源代码放在基于JNI
的库中
您可以在这里找到示例:这很奇怪。在
加载
的情况下,如果文件丢失,您应该得到不同的错误:无法加载库:
。他应该得到一个不满意的链接错误
,他是。实际文本取决于平台。通过绝对化当前工作目录,您的代码并不能完成任何事情。@user207421-谢谢您的评论并给出我的答案:)谢谢您的精彩:)ethsm真的是JNI库吗?或者仅仅是LunaMDUtil
所依赖的东西?如果是后者,则不应尝试加载它。@user207421ethsm
不是JNI库,而是包含我的C源文件实际调用的函数,因此不要尝试将其作为JNI库加载。如果它是一个.lib,那么您的C代码已经静态链接到它;否则,如果它是一个。那么您的C代码已经动态链接到它。您不需要再做了。@user207421-“如果它是一个。那么您的C代码已经动态链接到它了。您不需要再做了。”-恐怕这不是真的。这取决于系统,但链接到。因此
是不够的。您必须确保您链接到的.so
位于LD\u LIBRARY\u路径上
,或者您链接到-rpath
。否则,系统将看不到库java.library.path
仅对使用loadLibrary
加载的库有效,而不适用于此库所依赖的其他库。在Windows中,此库必须位于路径上
@Oo.Oo请注意上下文。就链接和加载而言,这已经足够了。当它不是JNI库时,您不必尝试将其作为JNI库加载。当然。所以必须在运行时出现,这是不言而喻的。关于java.library.path
,我一句话也没说。别把话塞进我嘴里。