Set java.library.path for testing

17,933

Solution 1

As in Sachin Handiekar's comment, the issue is solved by setting LD_LIBRARY_PATH in the environment in which Idea is run. (But not in Idea settings, for some reason.)

Solution 2

You can add system properties to the maven-surefire-plugin when the tests are running with the help of the systemPropertyVariables attribute:

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

This will add the java.library.path as a system property when the tests are ran. The modification you are making is not taken into account since the tests are ran in a forked VM.

Solution 3

You are most likely encountering this problem because you are using a Maven plugin like surefire or failsafe which launches a new JVM to run your tests and your launch configuration is not getting passed on. Also, you probably also need to set the 'java.library.path' on the command line of the new process so that the native library and all of its dependencies can be linked at startup. If you use 'systemPropertyVariables' it won't have the same effect, but might work if you lucky. Here is an example plugin configuration that is working for me:

        <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>
Share:
17,933

Related videos on Youtube

Michael Ivko
Author by

Michael Ivko

Updated on September 14, 2022

Comments

  • Michael Ivko
    Michael Ivko over 1 year

    One of the tests uses a native library:

    System.loadLibrary("mylib");
    

    libmylib.so is located in /usr/local/lib, So I add this directory in configuration VM options: -Djava.library.path=/usr/local/lib

    However, when I run tests with Maven, this line throws UnsatisfiedLinkError:

    no mylib in java.library.path

    Java is invoked without this option:

    /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
    

    Printing System.getProperty("java.library.path") when catching the exception gives /opt/idea/bin::/usr/java/packages/lib/amd64:/usr/lib64:/lib64:/lib:/usr/lib. Apparently VM options from run configuration have no effect on maven tasks.

    So I tried to set library path in VM options for Maven: Settings->Build, Execution, Deployment->Build Tools->Maven->Runner->VM options. This option has the effect on java invocation command:

    /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
    

    But even though Java is now invoked with this option, it still fails to load the library, and System.getProperty("java.library.path") still contains the same thing!

    How to set java.library.path for tests invoked with Maven?

    • Michael Ivko
      Michael Ivko about 8 years
      Yes, setting LD_LIBRARY_PATH actually helps!
    • Sachin
      Sachin
      Have you tried using the LD_LIBRARY_PATH env. variable ? Also have you tried to use System.load("/usr/local/lib/libmylib.so"); ?
  • Michael Ivko
    Michael Ivko about 8 years
    This probably would help, but I'd avoid it because it make pom.xml dependent on peculiarities of build environment.
  • Tunaki
    Tunaki about 8 years
    @MichaelIvko But the POM should be self-contained. So it should be dependent on peculiarities of the build environement. The problem with your solution is that it entirely depends on a 3rd party IntelliJ to hold the info. If you were to build this on the command line or on a CI server, it wouldn't work anymore, which goes against the principle of using Maven.
  • Tunaki
    Tunaki about 8 years
    The problem with that is that it makes your build dependant of IntelliJ when it shouldn't be. Everything should be in the POM so that the project can be build elsewhere. So with this solution, it won't work on the command line for example.
  • Michael Ivko
    Michael Ivko about 8 years
    Adding a dependency on files in a specified external directory does not make POM self-contained. The fact that the library is not included in explicit dependencies is probably against maven principles, but I needed to build the project as it is.
  • Dawood ibn Kareem
    Dawood ibn Kareem about 6 years
    You really shouldn't do this. The whole idea with maven is that the pom file is supposed to contain all the information you need to build, and that the build shouldn't rely on IntelliJ, or on any configuration that exists outside of the pom file. This might work locally on your computer, but it won't help if you're working in a team, or if you have any kind of continuous integration in your environment.
  • Heri
    Heri over 3 years
    Version 3.0 of maven-surefire-plugin shows warning: java.library.path cannot be set as system property, use <argLine> ... (see example in ajschmidt's answer)
  • Heri
    Heri over 3 years
    A note to the location of the library: I think a library on which a project is dependent should be part of the Workspace (SCM), or provided by a well defined repository (version controlled) during build process. Then you can work with a relative path. And you are sure that your tests use the same binaries as the productive server will do.
  • dimirsen Z
    dimirsen Z over 3 years
    You posted a copy of config from the manual. It should be adapted this way: <systemPropertyVariables> <java.library.path>/usr/local/lib</java.library.path> <buildDirectory>${project.build.directory</buildDirectory> </systemPropertyVariables>