Search code examples
javamavenjaruberjar

UnsatisfiedLinkError when trying to run an executable jar containing dependencies


My Java project has a number of dependencies e.g Box2d, OpenGl and OpenAl
I have the follow list of plugins defined in my pom.xml, so using Maven to manage project.
Note: I have dependencies listed at bottom of pom.xml, but excluding from here.

I followed this documentation to get started: http://maven.apache.org/plugins/maven-shade-plugin/examples/executable-jar.html

<plugins>
    <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.1</version>
        <configuration>
            <source/>
            <target/>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-shade-plugin</artifactId>
        <version>2.3</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>shade</goal>
                </goals>
                <configuration>
                    <transformers>
                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                            <mainClass>com.app.game.Main</mainClass>
                        </transformer>
                    </transformers>
                </configuration>
            </execution>
        </executions>
    </plugin>
</plugins>

When I run mvn package, a jar is created i.e target/test-0.1.jar
It actually contains all jar dependencies and includes native .so and .dll libraries at root of package.

enter image description here

But when I try run the application from CLI, I get UnsatisfiedLinkError exception.
Am I missing something in pom?

[rob@work target]$ java -jar test-0.1.jar 
log4j:WARN No appenders could be found for logger (com.app.game.Main).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Catched FileNotFoundException: /home/rob/git/test/target/test-0.1-natives-linux-amd64.jar (No such file or directory), while addNativeJarLibsImpl(classFromJavaJar class com.jogamp.common.os.Platform, classJarURI jar:file:/home/rob/git/test/target/test-0.1.jar!/com/jogamp/common/os/Platform.class, nativeJarBaseName test-0.1-natives-linux-amd64.jar): [ file:/home/rob/git/test/target/test-0.1.jar -> file:/home/rob/git/test/target/ ] + test-0.1-natives-linux-amd64.jar -> slim: jar:file:/home/rob/git/test/target/test-0.1-natives-linux-amd64.jar!/
Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/rob/git/test/target/libgluegen-rt.so (/home/rob/git/test/target/liblibgluegen-rt.so.so: cannot open shared object file: No such file or directory)
    at java.lang.ClassLoader.loadLibraryWithPath(ClassLoader.java:1217)

Solution

  • Using following set of plugins in POM.xml achieved what I was looking for ..

    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.4</version>
        <configuration>
            <descriptors>
                <descriptor>src/assembly/assembly.xml</descriptor>
            </descriptors>
        </configuration>
        <executions>
            <execution>
                <id>make-assembly</id>  <!-- this is used for inheritance merges -->
                <phase>verify</phase>  <!-- bind to the verify phase, to execute after package phase -->
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>appassembler-maven-plugin</artifactId>
        <version>1.7</version>
        <configuration>
            <programs>
                <program>
                    <mainClass>com.app.game.Main</mainClass>
                    <id>thegame</id>
                </program>
            </programs>
            <repositoryName>lib</repositoryName>
            <repositoryLayout>flat</repositoryLayout>
            <assembleDirectory>${project.build.directory}/${project.artifactId}</assembleDirectory>
        </configuration>
        <executions>
            <execution>
                <id>prepare-assembly</id>  <!-- this is used for inheritance merges -->
                <phase>package</phase>  <!-- bind to the package phase -->
                <goals>
                    <goal>assemble</goal>
                </goals>
            </execution>
        </executions>
    </plugin>
    

    And src/assembly/assembly.xml ..

    <?xml version="1.0" encoding="UTF-8"?>
    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
        <id>bin</id>
        <formats>
            <format>zip</format>
        </formats>
        <fileSets>
            <fileSet>
                <directory>${project.build.directory}/${project.artifactId}</directory>
                <outputDirectory>/</outputDirectory>
                <includes>
                    <include>/**</include>
                </includes>
                <excludes>
                    <exclude>bin/*</exclude>
                </excludes>
            </fileSet>
            <fileSet>
                <directory>${project.build.directory}/${project.artifactId}/bin</directory>
                <lineEnding>keep</lineEnding>
                <useDefaultExcludes>true</useDefaultExcludes>
                <outputDirectory>bin</outputDirectory>
                <includes>
                    <include>*</include>
                </includes>
                <fileMode>755</fileMode>
            </fileSet>
        </fileSets>
    </assembly>