Search code examples
javac++java-native-interfaceunsatisfiedlinkerror

Java JNI UnsatisfiedLinkError


I'm trying to expose C++ functionality to Java using JNI. I'm trying to get a simple message box to show up first, just to make sure everything works. However, I'm getting an UnsatisfiedLinkError exception being thrown (the exception is being thrown when I call the function, not)

Java class (project cpplib):

package src;

public class MessageBox {
    static {
        System.loadLibrary("cpplib");
    }

    private static native void libf_show(String message, String caption);

    public static void show(String message, String caption) {
        libf_show(message, caption);
    }
}

Note: the folder of cpplib, the DLL, has been added into the native libraries path

C++ header messagebox.hpp:

#pragma once

#include "jni.h"

extern "C"
{
    JNIEXPORT void JNICALL Java_cpplib_src_MessageBox_show(JNIEnv *env, jstring jstr_message, jstring jstr_caption);
}

C++ source messagebox.cpp:

#include "messagebox.hpp"
#include <windows.h>

JNIEXPORT void JNICALL Java_cpplib_src_MessageBox_show(JNIEnv *env, jstring jstr_message, jstring jstr_caption)
{
    const char *message = env->GetStringUTFChars(jstr_message, 0);
    const char *caption = env->GetStringUTFChars(jstr_caption, 0);

    MessageBox(NULL, message, caption, MB_OK);

    env->ReleaseStringUTFChars(jstr_message, message);
    env->ReleaseStringUTFChars(jstr_caption, caption);
}

Full error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: src.MessageBox.libf_show(Ljava/lang/String;Ljava/lang/String;)V
at src.MessageBox.libf_show(Native Method)
at src.MessageBox.show(MessageBox.java:11)
at src.CPPLIB_Test.main(CPPLIB_Test.java:6)

I believe I'm using the 64-bit version of the JDK (as a 32-bit DLL didn't work), so I'm using the appropriate 64-bit JDK headers (if they are different at all).

Why doesn't Java like my DLL?


Solution

  • I tried to reproduce your problem but I get different header. If a recreate your MessageBox.java inside a src directory and compile with javac -d build src/MessageBox.java and finally obtain C/C++ headers with javah -d include -classpath build src.MessageBox

    Then, I got this method signature

    JNIEXPORT void JNICALL Java_src_MessageBox_libf_1show (JNIEnv *, jclass, jstring, jstring);
    

    instead

    JNIEXPORT void JNICALL Java_cpplib_src_MessageBox_show(JNIEnv *env, jstring jstr_message, jstring jstr_caption);
    

    How are you creating your C++ header? maybe here it is the problem.