3
votes

I'm trying to work build my very first JNI application, following this tutorial: https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html

Problem Summary: While running my application, I get an java.lang.UnsatisfiedLinkError error.

First I wrote the Class HelloJNI.java:

public class HelloJNI {
   static {
      System.loadLibrary("hello"); // Load native library at runtime
                                   // hello.dll (Windows) or libhello.so (Unixes)
   }

   // Declare a native method sayHello() that receives nothing and returns void
   private native void sayHello();

   // Test Driver
   public static void main(String[] args) {
      new HelloJNI().sayHello();  // invoke the native method
   }
}

This class I compiled with: javac HelloJNI.java Next I ran javah HelloJNI This produced the following file HelloJNI.h:

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

#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloJNI
 * Method:    sayHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloJNI_sayHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

Next I implemented HelloJNI.c:

#include <jni.h>
#include <stdio.h>
#include "HelloJNI.h"

// Implementation of native method sayHello() of HelloJNI class
JNIEXPORT void JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj) {
   printf("Hello World!\n");
   return;
}

Finally I compiled the c class:

  • gcc -I"/usr/lib/jvm/java-8-oracle/include" -I"/usr/lib/jvm/java-8-oracle/include/linux" -c -Wall -Werror -fpic HelloJNI.c
  • gcc -shared -o hello.so HelloJNI.o

This produces the files hello.so and HelloJNI.o. Next I try to run the code:

  • java -Djava.library.path=. HelloJNI This produces the error:

    Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1864) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at HelloJNI.(HelloJNI.java:3)

This seems to be the most common JNI error on the internet... My method names seem to be correct. I also ran:

  • nm hello.so | grep say

This gives me: 00000000000006b0 T Java_HelloJNI_sayHello which seems to be correct, i.e. the compiler didn't add additional characters. I simply ran out of ideas of things I could try. Any suggestions?

My OS: Linux Mint 13, GCC version 4.7.3, java version 1.8.0_60

==========UPDATE=============== When I replace System.loadLibrary("hello"); by System.load("/usr0/home/jkinable/workspace/javaIDEA/jnitest/hello.so"); my HelloWorld example works! However, I don't want to use an absolute path so I'm still looking for a way to use System.loadLibrary("hello"); instead? Any suggestions? I've also tried running on a different linux system, but I get the same issue.

1
Based on the error message, it looks like the problem isn't that the function can't be found, but rather that the entire library can't be found.Michael
Probably you are right (see update). Not sure how to fix it though :(Joris Kinable

1 Answers

3
votes

It turns out that the problem is due to some naming convention on unix/linux platforms! When using: System.loadLibrary("hello"); the file should not be named hello.so! Instead, the name should be libhello.so. On Windows, use hello.dll. I'm surprised that this issue is not mentioned in IBM's JNI tutorial: http://www.ibm.com/developerworks/java/tutorials/j-jni/j-jni.html

I'm not sure what the rationality behind this issue is. Why would you load a library "hello" which should be named libhello.so on your filesystem (instead of hello.so)?