【问题标题】:Does Tomcat (as a Service) not load native libraries for a Java web application?Tomcat(即服务)是否不会为 Java Web 应用程序加载本机库?
【发布时间】:2016-06-30 18:56:51
【问题描述】:

我正在使用 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 的错误。

我也愿意将本机库添加为应用程序的 .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) 调用/加载第二个库 (libmachoman.so)。找到并加载了 libcore.so 和 libmachoman.so 都没有,即使两者都在同一个位置。

【问题讨论】:

  • 你能看到启动日志中设置的库路径吗?
  • @11thdimension 谢谢。不,我没有看到 Tomcat 选择了我在上面设置的路径。感谢您提供这些新知识。我怎样才能确保它确实如此?我只是将tomcat的日志添加到问题中。
  • 在你提到的问题标题中,tomcat 作为服务运行。您可以在此处找到为 Tomcat 创建服务和参数的脚本。
  • @11thdimension 这听起来像是一个艰难的解决方案,尤其是因为我正在部署多个系统而不仅仅是一个服务器。我宁愿有一个特定于应用程序的解决方案,也不愿更改系统设置。将本机库作为 .war 文件的一部分导出对我有用,但我不知道该怎么做。
  • 你能不能试着不把它们放在 /home/* 目录下。以防万一 /home/ 给出奇怪的结果。

标签: java eclipse web-services tomcat catalina


【解决方案1】:

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

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

以库的绝对路径为例

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

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

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

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

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

【讨论】:

  • 我进一步查看,发现库位置可能没有问题,至少对于第一个库来说是这样——然后它调用了第二个库。第一个库是第二个库的包装器。第一个已找到并加载,因此 catalina.out 文件中没有错误,但只要第一个库到达加载它的点,就找不到第二个库。这很奇怪,因为该应用程序可以独立运行。更新的问题。
  • 在独立版本中打印 System.getProperty("java.library.path") 然后在 Web 应用程序中打印相同的内容,比较打印的值这可能会提供线索。
  • 在 Java 应用程序中,我使用 System.loadLibrary("lib_mymainlib.so") 加载初始库,第二个库以本机代码加载为 dlopen("lib_mynative_lib.so", 1)。我想知道这是否有区别。我会尝试按照建议添加调试消息。
  • 可能为lib_mynative_lib.so 调用System.loadLibrary() 也会有所作为。
【解决方案2】:

在头痛了几天之后,我有了一个解决办法。

  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 的一部分;更清洁的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 2011-01-20
    相关资源
    最近更新 更多