Ivaylo Toskov
Ivaylo Toskov

Reputation: 4021

How to resolve UnsatisfiedLinkError when using JNI with packages?

Firstly, my example has the following directory structure:

Sample.c
lib/
mypackage/
--Sample.java

Sample.java in mypackage looks like this:

package mypackage;

public class Sample {
    public static native int sampleMethod(int x);

    public static void main(String[] args) {
        System.loadLibrary("Sample");
        System.out.println("sampleMethod result: " + sampleMethod(5));
    }
}

I run javac mypackage/Sample.java to compile the java file and javah mypackage.Sample to generate the JNI headers. Then I compile the library using the following command:

clang -I"${JAVA_HOME}/include" -I"${JAVA_HOME}/include/darwin" -o lib/libSample.so -shared Sample.c

At this point the directory structure looks like this:

Sample.c
mypackage_Sample.h
lib/
--libSample.so
mypackage/
--Sample.java
--Sample.class

Now when I try to run the example using java -Djava.library.path=./lib/ mypackage.Sample I get the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no Sample in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867)
    at java.lang.Runtime.loadLibrary0(Runtime.java:870)
    at java.lang.System.loadLibrary(System.java:1122)
    at mypackage.Sample.main(Sample.java:7)

I tried specifying the full path to lib/, but I get the same error.

I am not sure if the code for the header and the implementation matter, but I will post them anyway.

mypackage_Sample.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class mypackage_Sample */

#ifndef _Included_mypackage_Sample
#define _Included_mypackage_Sample
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     mypackage_Sample
 * Method:    sampleMethod
 * Signature: (I)I
 */
JNIEXPORT jint JNICALL Java_mypackage_Sample_sampleMethod
  (JNIEnv *, jclass, jint);

#ifdef __cplusplus
}
#endif
#endif

Sample.c:

#include "mypackage_Sample.h"
#include <stdio.h>

JNIEXPORT jint JNICALL Java_mypackage_Sample_sampleMethod
  (JNIEnv * env, jclass obj, jint num) {
      return num * num;
  }

I run this on OS X Yosemite 10.10.5 using clang 7.0.2 and java 1.8.0_101.

Upvotes: 1

Views: 752

Answers (1)

Jorn Vernee
Jorn Vernee

Reputation: 33845

It looks like you have the wrong name from your library file (libSample.so).

If you use:

System.loadLibrary("Sample");

The JVM will map this name to a platform specific file name to try and load. On Linux that is libSample.so, on Windows that is Sample.dll, but on OS X it's something else.

You can find out which name your library file should have by looking at the output of:

System.mapLibraryName("Sample");

Called on the target platform.

After that, you can use that as the name of your library file.

Upvotes: 1

Related Questions