【问题标题】:jna Native.LoadLibrary does not manage to load library on server (working in local)jna Native.LoadLibrary 无法在服务器上加载库(在本地工作)
【发布时间】:2026-01-13 17:20:02
【问题描述】:

我使用 JNA 在 java 项目中加载 c++ 库 (.so)。我将我的库打包在 jar 中,并在实例化使用它的 java 类时从 jar 中加载它。我都是这样做的:

  • mvn install 编译 c++ 代码并将结果动态库打包到 jar 中。
  • 我在实例化 LibraryWrapperClass 时在静态上下文中调用以下内容

    System.load( temp.getAbsolutePath() );
    

temp 是一个临时文件,其中包含在 jar 中找到的库。此代码基于此处找到的工作adamheinrich - 我调用Native.loadLibrary(LIBRARYPATH) 将库包装到java 类中。

    private interface Wrapper extends Library {
        Wrapper INSTANCE = Native.loadLibrary( C_LIBRARY_PATH, Wrapper.class );

        Pointer Constructor();
        ...
    }
  • 我运行测试并验证库是否已找到并且已启动并正在运行。
  • 我使用一个依赖于这个项目的 java web 项目。它使用tomcat并在本地运行良好。

我的问题是,当我在服务器上部署时,LibraryWrapperClass 无法实例化。服务器上的错误是:

java.lang.NoClassDefFoundError: Could not initialize class pacakgeName.LibraryWrapperClass
    at java.base/java.lang.Class.forName0(Native Method)
    at java.base/java.lang.Class.forName(Class.java:375)
    at org.hibernate.annotations.common.util.StandardClassLoaderDelegateImpl.classForName(StandardClassLoaderDelegateImpl.java:57)
    at org.hibernate.boot.internal.MetadataBuilderImpl$MetadataBuildingOptionsImpl$4.classForName(MetadataBuilderImpl.java:758)
    at org.hibernate.annotations.common.reflection.java.JavaReflectionManager.classForName(JavaReflectionManager.java:144)
    at... 

这个错误似乎是找到了库,因为没有抛出UnsatisfiedLinkError异常。但其他事情正在失败。有人知道会发生什么吗?我该如何调试?

我记得一切都在本地完美运行。

【问题讨论】:

  • 我认为pacakgeName 只是一种类型,对吧?
  • 我不想透露确切的包名,因为它包含私人信息。
  • 当然,它的行为并没有什么不同。唯一不同的是有效路径。
  • 所以你的意思是找不到库?我怎么能建议让它看正确的位置?我怎样才能证明你的观点是造成我麻烦的原因?

标签: java tomcat noclassdeffounderror jna


【解决方案1】:

我该如何调试?

1.用 strace

strace 将为您提供 Tomcat 试图打开的文件:strace -f -e trace=file -o log.txt bin/startup.sh

在此之后,在 log.txt 中查找 packageName,或其他未找到的文件:

egrep ' open.*No such file' log.txt

2。使用 JConsole

启用 JMX,启动 JConsole,转到 VM 摘要选项卡,并非常仔细地检查/比较 VM 参数/类路径/库路径/引导类路径

3.使用 ldd 列出依赖项

如果可能是依赖关系问题,ldd sharedLibraryFile.so 命令会列出所有依赖关系并允许跟踪可能缺少的依赖关系。

【讨论】:

  • 感谢您的回答。很奇怪,因为包名没有出现在日志中。我什至不觉得这个日志包含任何错误,尽管我不确定如何解释日志。而且c++的libc.so.6是和g++一起找到的。
  • 我相信该库已找到,但缺少依赖项。我不知道如何发现它...
  • @EJP 说你有不同的路径,这会导致文件找不到,strace 能够准确地看到。我会做 egrep ' open.*No such file' log.txt 来找出哪些文件没有找到
  • 如果我执行grep ' open.*' log.txt,那么我会看到所有未找到的文件首先会在另一个目录中找到。没有一个是指我提供的路径。谢谢
  • 选项 3 是我的问题的解决方案。谢谢