设置 java.library.path 进行测试

Set java.library.path for testing

其中一项测试使用本机库:

System.loadLibrary("mylib");

libmylib.so位于/usr/local/lib,所以我在配置VM选项中添加这个目录:-Djava.library.path=/usr/local/lib

但是,当我 运行 使用 Maven 进行测试时,此行抛出 UnsatisfiedLinkError:

no mylib in java.library.path

Java 在没有此选项的情况下被调用:

/usr/lib/jvm/java-8-oracle/bin/java -Dmaven.home=/opt/idea/plugins/maven/lib/maven3 -Dclassworlds.conf=/opt/idea/plugins/maven/lib/maven3/bin/m2.conf -Didea.launcher.port=7538 -Didea.launcher.bin.path=/opt/idea/bin -Dfile.encoding=UTF-8 -classpath /opt/idea/plugins/maven/lib/maven3/boot/plexus-classworlds-2.4.jar:/opt/idea/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain org.codehaus.classworlds.Launcher -Didea.version=15.0.3 test

捕获异常时打印 System.getProperty("java.library.path") 给出 /opt/idea/bin::/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib。显然 运行 配置中的 VM 选项对 Maven 任务没有影响。

所以我尝试在 Maven 的 VM 选项中设置库路径:Settings->Build, Execution, Deployment->Build Tools->Maven->Runner->VM options .此选项对 java 调用命令有影响:

/usr/lib/jvm/java-8-oracle/bin/java -Djava.library.path=/usr/local/lib -Dmaven.home=/opt/idea/plugins/maven/lib/maven3 -Dclassworlds.conf=/opt/idea/plugins/maven/lib/maven3/bin/m2.conf -Didea.launcher.port=7539 -Didea.launcher.bin.path=/opt/idea/bin -Dfile.encoding=UTF-8 -classpath /opt/idea/plugins/maven/lib/maven3/boot/plexus-classworlds-2.4.jar:/opt/idea/lib/idea_rt.jar com.intellij.rt.execution.application.AppMain org.codehaus.classworlds.Launcher -Didea.version=15.0.3 test

但是即使现在用这个选项调用Java,它仍然无法加载库,并且System.getProperty("java.library.path")仍然包含相同的东西!

如何为使用 Maven 调用的测试设置 java.library.path

您可以add system properties to the maven-surefire-plugin when the tests are running with the help of the systemPropertyVariables属性:

<plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.19.1</version>
  <configuration>
    <systemPropertyVariables>
      <propertyName>java.library.path</propertyName>
      <buildDirectory>/usr/local/lib</buildDirectory>
    </systemPropertyVariables>
  </configuration>
</plugin>

这将在测试 运行 时将 java.library.path 添加为系统 属性。由于测试是 运行 在分叉的 VM 中进行的,因此不会考虑您所做的修改。

如 Sachin Handiekar 的评论所述,通过在 Idea 为 运行 的环境中设置 LD_LIBRARY_PATH 解决了该问题。 (但出于某种原因,不在创意设置中。)

"native library path not passed through to Maven by Intellij"问题的解决方案:

我发现您可以使用 JVM 已经搜索到的本地目录。

首先,在您的 Junit 测试或实时代码中使用 System.out 消息打印您的 java.library.path。

在我的 Mac 上,我得到以下信息:

/Users/gareth/Library/Java/Extensions:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java:.

这个库路径的第一部分为我们提供了解决问题的方法,因为 JVM 首先搜索用户的本地目录 (/Users/gareth/Library/Java/Extensions),我们可以将 jnilib 文件符号链接到这里:

所以:

$ mkdir -p /Users/gareth/Library/Java/Extensions

$ cd /Users/gareth/Library/Java/Extensions

$ ln -s /Users/gareth/Applications/IBM/ILOG/CPLEX_Studio_Community127/cplex/bin/x86-64_osx/libcplex1270.jnilib libcplex1270.jnilib

这是自定义的“每个用户”操作的不便之处,但似乎并不比 IDE 中的 "per user" 更糟糕。

现在,在 Intellij 内的单个单元测试运行期间以及从 "maven test".

内的运行中都可以获取本机库

您很可能会遇到此问题,因为您正在使用 Maven 插件,例如 surefire 或 failsafe,它会启动一个新的 JVM 来 运行 您的测试,并且您的启动配置没有得到传递。此外,您可能还需要在新进程的命令行上设置 'java.library.path',以便在启动时可以链接本机库及其所有依赖项。如果你使用 'systemPropertyVariables' 它不会有同样的效果,但如果你幸运的话可能会起作用。这是一个适用于我的示例插件配置:

        <plugin>
            <artifactId>maven-failsafe-plugin</artifactId>
            <version>2.19</version>
            <executions>
                <execution>
                    <id>my-external-tests</id>
                    <goals>
                        ...
                    </goals>
                    <configuration>
                        <argLine>-Djava.library.path=/usr/local/lib</argLine>
                        <groups>com.myCompany.ExternalTest</groups>
                        <includes>
                            <include>**/*Suite.java</include>
                        </includes>
                    </configuration>
                </execution>
            </executions>
        </plugin>

您可以像这样在 maven surefire 插件中配置 VM 选项,

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <argLine>-Djava.library.path=/usr/local/lib</argLine>
                </configuration>
                ....
</plugin>

参考:https://maven.apache.org/surefire/maven-surefire-plugin/examples/system-properties.html