Gcc 如何通过进行最小的更改来修复不满意的链接错误?

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")

我正在尝试在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
    }

}
(我省略了代码,因为我认为它与问题无关。)

在我的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
所依赖的东西?如果是后者,则不应尝试加载它。@user207421
ethsm
不是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
,我一句话也没说。别把话塞进我嘴里。