Search code examples
javamavenjna

java.lang.UnsatisfiedLinkError on calling Native.loadLibrary()


I'm trying to call a method from a .dll, using com.sun.jna.Native. It works fine when run from IntelliJ, but crashes when executed as a .jar file.

How do I fix it, so that the .jar is able to call the method from the .dll too?

Startup.java:

package de.company;
import com.sun.jna.Library;
import com.sun.jna.Native;

public class Startup {

    public interface LibInterface extends Library {
        public String getA(int a, int b, int c, String d);
        public String getB(int a, int b, int c, String d);
    }


    public static void main(String[] args){
        System.out.println("hello world");

        try{
            LibInterface library = (LibInterface) Native.loadLibrary("NameOfLibraryWithoutDotDll", LibInterface.class);
            System.out.println("Successfully loaded the library");

            System.out.println("Result of the call: " + library.getA(1,2,3,"asdf"));
        }catch(Exception e){
            System.out.println("Exception: " + e.getMessage());
        }
    }
}

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>Test</artifactId>
<groupId>de.company</groupId>
<version>1.0-SNAPSHOT</version>
<name>Test</name>
<description>Dinghy to test JNA</description>
<dependencies>
    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna</artifactId>
        <version>4.2.1</version>
    </dependency>
</dependencies>
<build>
    <finalName>${artifactId}</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <executions>
                <execution>
                    <id>copy-dependencies</id>
                    <phase>prepare-package</phase>
                    <goals>
                        <goal>copy-dependencies</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${project.build.directory}/lib</outputDirectory>
                        <overWriteReleases>false</overWriteReleases>
                        <overWriteSnapshots>false</overWriteSnapshots>
                        <overWriteIfNewer>true</overWriteIfNewer>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>de.company.Startup</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

When I run the code from inside IntelliJ, I get the output:

hello world

Successfully loaded the library

Result of the call: FooBar

But when I run the jar file from a commandline, even when started with administrator privileges, via:

mvn clean install
java -jar -Djna.debug_load=true target/test.jar 

I get the following console output:

Hello world
Looking in classpath from sun.misc.Launcher$AppClassLoader@55f96302 for /com/sun/jna/win32-x86-64/jnidispatch.dll
Found library resource at jar:file:/D:/dev/Test/target/lib/jna-4.2.1.jar!/com/sun/jna/win32-x86-64/jnidispatch.dll
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\CAA\AppData\Local\Temp\jna--517937128\jna2553495241482547583.dll: %1 is not a valid Win32 application
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.load0(Unknown Source)
at java.lang.System.load(Unknown Source)
at com.sun.jna.Native.loadNativeDispatchLibraryFromClasspath(Native.java:851)
at com.sun.jna.Native.loadNativeDispatchLibrary(Native.java:826)
at com.sun.jna.Native.<clinit>(Native.java:140)
at de.company.Startup.main(Startup.java:17)

Update:

If i attempt to load a dll that does not exist, I get the same error.

The folder C:\Users\CAA\AppData\Local\Temp\jna--517937128\ got created by the JNA framework, but it doesn't contain any files.


Solution

  • It seems like this is an issue with the version of JNA that I used. Updating it to the newest fixed that error.

    pom.xml:

    <dependency>
        <groupId>net.java.dev.jna</groupId>
        <artifactId>jna</artifactId>
        <version>5.15.0</version>
    </dependency>