Tomcat(作为服务)是否不为 Java 网络应用程序加载本机库?

Does Tomcat (as a Service) not load native libraries for a Java web application?

我正在使用 Tomcat7 和 Ubuntu。我有一个 Java Web 应用程序,它使用了一些本机库。当我 运行 Eclipse 中的 Web 应用程序时,它在调试期间通过 Eclipse 内部 Tomcat 服务器工作。但是,当我将应用程序部署到托管 Tomcat 服务时,应用程序在到达加载这些库的点时失败。

  1. 我把原生库放在/home/me/my_shared_libs,给了
    文件夹和文件所有权归用户 "Tomcat7" -- sudo chown
  2. 我将本机库的所有权限授予 "Tomcat7" 用户 -- sudo chmod
  3. sudo vi /usr/share/tomcat7/bin/setenv.sh 中,并放入以下内容 在文件中 export CATALINA_OPTS="-Djava.library.path=/home/me/my_shared_libs"
  4. 然后我重新启动 Tomcat -- sudo service tomcat7 restart 而且,每当 已达到加载本机库的引用,我收到有关 InvocationTargetException.
  5. 的错误

我也愿意选择将本机库添加为应用程序 .WAR 文件的一部分。 (虽然我不确定如何在 Eclipse 中执行此操作)。

/var/log/tomcat7/catalina.out 的日志-->

Jun 30, 2016 8:11:50 PM org.apache.catalina.startup.Catalina start
INFO: Server startup in 3643 ms
Load my_native_lib_called. libmachoman.so: cannot open shared object file: No such file or directory

编辑: 我发现了一件非常有趣的事情。 Tomcat 确实选择了我在上面设置的库位置。发生的情况是我在该位置有两种类型的库 (.so) 文件。第一个库 (libcore.so) calls/loads 第二个库 (libmachoman.so)。 libcore.so 已找到并加载,libmachoman.so 未找到,即使两者位于同一位置。

可以从代码本身完成。这应该会让您对库的加载充满信心。

为此,您可以使用 System.load()

以库的绝对路径为例

System.load("/PATH/TO/.so");

运行这段代码在应用程序启动时调用库函数之前一次。

您必须将您的图书馆放在所有服务器上的自定义位置。

System.loadLibrary() 也用于相同的目的,但不同之处在于它会按名称加载库并查看 Java 环境变量 java.library.path 指定的位置。

但是正如您所提到的,设置起来可能会很痛苦,必须在 tomcat 的所有实例中进行此更改。

头疼了几天,终于有了解决办法。

  1. 编辑文件

    sudo vi /etc/ld.so.conf

  2. 在文件中追加本机库的位置

    包括/etc/ld.so.conf.d/*.conf /home/me/my_shared_lib

  3. 加载配置

    sudo ldconfig

  4. 查看新变化

    ldconfig -p | grep my_shared_lib

这告诉动态链接器在哪里寻找本机库。

我的问题解决了。

还有其他替代解决方案 here,它们可能有也可能没有一些缺点。

或者(也发现),您可以在 /usr/share/tomcat7/bin/ 下的 setenv.sh 文件中导出 LD_LIBRARY_PATH 而不是上述步骤。设置成为 Tomcat 的一部分;更清洁的方法。