JNI Hello World Unsatisfied Link Error

后端 未结 5 1186
抹茶落季
抹茶落季 2020-11-30 13:58

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 erro

相关标签:
5条回答
  • 2020-11-30 14:12

    I just removed -MD option and compiled it worked like charm

    cl -I"C:\Program Files\Java\jdk1.6.0_21\include" -I"C:\Program Files\Java\jdk1.6.0_21\include\win32" -LD HelloWorld.c -FeHelloWorld.dll
    
    0 讨论(0)
  • 2020-11-30 14:24

    If you change the location (package) of your native function declaration from the java side without updating the h file, and the signature of the method in the c++ side, It won't resolve to the method and will throw unsatisfied..

    package x;
    public class A {
        private native void print();
        ...
    }
    

    moved to:

    package x.y;
    public class A {
        private native void print();
        ...
    }
    

    This will require regeneration of the H file (to something like Java_x_y_A_print ).

    Note you can change those signatures manually but I won't recommend

    0 讨论(0)
  • 2020-11-30 14:35

    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

    0 讨论(0)
  • 2020-11-30 14:37

    I'm not claiming to understand the situation enough to explain it, however some users reported the error when using the "-MD" compiler flag.

    For more information see Java Native Interface (JNI) - Impossible to use VS2005 with Java? which discusses this problem and offers possible work-arounds and think techie blog for alternatives.

    0 讨论(0)
  • 2020-11-30 14:37

    I believe that you should be using

    System.loadLibrary("HelloWorld");
    

    instead of System.load. LoadLibrary will check your system path (not the Java library path) so make sure that HelloWorld.dll is in a directory where it can found. Also note that it does not require the full path, and you don't need to add the dll extension to the end.

    0 讨论(0)
提交回复
热议问题