Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JNI Hello World Unsatisfied Link Error

This is my first attempt at JNI. My ultimate goal is to get all tasks currently running on a machine, but need to get even a simple example running. I keep getting this error when I try to execute my main program. I have supplied my simple Java main program, the header file generated, and the error.

I do not know what this DLL could be dependent on. It was initially referencing a DLL I tracked down and placed into system32 (msvcr90.dll).

Here is the command I used to compile the C code as well which produced the DLL, OBJ, LIB, EXP and manifest files.

cl -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\Java\jdk1.6.0\include\win32" -MD -LD HelloWorld.c -FeHelloWorld.dll

class HelloWorld {
     private native void print();
     public static void main(String[] args) {
         new HelloWorld().print();
     }
     static {
         System.load("C:\\temp\\HelloWorld.dll");
     }
 }


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

 JNIEXPORT void JNICALL 
 Java_HelloWorld_print(JNIEnv *env, jobject obj)
 {
     printf("Hello World!\n");
     return;
 }

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

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

java.lang.UnsatisfiedLinkError: C:\temp\HelloWorld.dll: A dynamic link library (DLL) initialization routine failed
    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 HelloWorld.<clinit>(HelloWorld.java:7)
Exception in thread "main" 
like image 347
Ken Avatar asked Aug 31 '09 17:08

Ken


People also ask

What is UnsatisfiedLinkError in Java?

UnsatisfiedLinkError runtime error. More specifically, this error is thrown whenever the JVM is unable to find an appropriate native-language definition of a method declared native , while attempting to resolve the native libraries at runtime [2].

What JNI calls?

In software design, the Java Native Interface (JNI) is a foreign function interface programming framework that enables Java code running in a Java virtual machine (JVM) to call and be called by native applications (programs specific to a hardware and operating system platform) and libraries written in other languages ...


1 Answers

The Unsatisfied Link Error can mean many things went wrong. I would use

System.loadLibrary("HelloWorld");

Instead of

System.load();

As TwentyMiles suggested.

Also, when invoking your program you need to (assuming your DLL is on the same directory as your class files:

java -Djava.library.path=. HelloWorld

Here's a simple demo I made that calls a Win32 API function (MessageBox)

Java class

class CallApi{
    private native String showMessageBox(String msg);
    private native double getRandomDouble();

    static{
        try{
            System.loadLibrary("CallApi");
            System.out.println("Loaded CallApi");
        }catch(UnsatisfiedLinkError e){
            //nothing to do
            System.out.println("Couldn't load CallApi");
            System.out.println(e.getMessage());
        }
    }

    public static void main(String args[]){
        CallApi api = new CallApi();
        double randomNumber = api.getRandomDouble();
        String retval = api.showMessageBox("Hello from Java!\n"+
            "The native random number: "+randomNumber);
            System.out.println("The native string: "+retval);
    }
}

Generated header file

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

#ifndef _Included_CallApi
#define _Included_CallApi
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CallApi
 * Method:    showMessageBox
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox
  (JNIEnv *, jobject, jstring);

/*
 * Class:     CallApi
 * Method:    getRandomDouble
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

The C DLL code

#include "CallApi.h"
#include <windows.h>
#include <stdlib.h>
#include <time.h>

#pragma comment(lib,"user32.lib")

JNIEXPORT jstring JNICALL Java_CallApi_showMessageBox
  (JNIEnv *env, jobject thisObject, jstring js)
{
    //first convert jstring to const char for use in MessageBox
    const jbyte* argvv = (*env)->GetStringUTFChars(env, js, NULL);
    char* argv =(char *) argvv;

    //Call MessageBoxA
    MessageBox(NULL, argv, "Called from Java!", MB_ICONEXCLAMATION | MB_OK);
    return js;
}

JNIEXPORT jdouble JNICALL Java_CallApi_getRandomDouble
  (JNIEnv *env, jobject thisObject)
{
    double num1;
    srand((unsigned)(time(0)));
    num1 = ((double)rand()/(double)RAND_MAX);

    return num1;
}

Compile instructions

I compile with the Visual C++ express 2008 cl, removing the -ML flag since it causes an exception when the Java code tries to call the native code:

cl /I"c:\Program Files\Java\jdk1.6.0_10\include" /I"c:\Program Files\Java\jdk1.6.0_10\include\win32" -LD CallApi.c -FeCallApi.dll

Then, to run the code:

java -Djava.library.path=. CallApi

like image 97
Cesar Avatar answered Sep 17 '22 01:09

Cesar