Search code examples
javacdlljava-native-interfacemingw

Java Native Interface Error: Can't load IA 32-bit .dll on an AMD 64-bit platform


I'm getting started with learning how to use the JNI. I'm following this basic instruction set on making Hello World with JNI here. I have the following files:

HelloJNI.java

      public class HelloJNI {

           static {
              System.loadLibrary("hello"); //Load native library hello.dll at runtime
           }

           //declare a native method sayHello() w/ no arguments and returns void
           private native void sayHello();

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

     }

The following header file is machine generated by running javah HelloJNI from the command line:

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

Finally I have the C code:

HelloJNI.c

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

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

I compile the C code into a .dll in windows using MinGW like so:

gcc -Wl,--add-stdcall-alias -I"%JAVA_HOME%\include" -I"%JAVA_HOME%\include\win32" -shared -o hello.dll HelloJNI.c

It compiles fine but when I try to run the java code java HelloJNI

I get the following error:

Exception in thread "main" java.lang.UnsatisfiedLinkError: E:\Users\Ryan\Repos\HelloJNI\hello.dll: Can't load IA 32-bit .dll on a AMD 64-bit platform
    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.loadLibrary0(Unknown Source)
    at java.lang.System.loadLibrary(Unknown Source)
    at HelloJNI.<clinit>(HelloJNI.java:4)

I'm assuming that I need to change how to compile the .dll with MinGW since there seems to be a 32 bit/ 64 bit mismatch. I haven't been able to find anything other than use the 64bit dll, which i don't have since I'm trying to compile it right now. Do I have to switch to 32 bit java or is there a way to compile the dll differently?


Solution

  • This indeed happens because you have a 32-bit DLL and you are using 64-bit Java.

    The "bitness" of the native library and the JVM you are using have to match. The only options you have are compiling the DLL to 64-bit, or use 32-bit Java. There is no way to make 64-bit Java load the 32-bit DLL.

    See for example this question on how to compile a 64-bit DLL with gcc on MinGW. The easiest thing to try is to use the -m64 switch when compiling the DLL.