JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application'

jni c++ class example
jni documentation
jni vs jna
jni component
jni call java from c
jni android
jni call java method from native code
jni performance

I am trying to actually get JNI working before I dive in with my actual code, but after I compile a DLL from C++ and run my Java application I get:

Exception in thread "main" java.lang.UnsatisfiedLinkError: <snip>\workspace\JNI test\native\jnitest.dll: %1 is not a valid Win32 application
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary1(Unknown Source)
    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 net.condorcraft110.jnitest.JNITest.main(JNITest.java:11)

Having Googled this for a bit, I know that this is usually caused by trying to load a 64 bit DLL with a 32 bit JVM. However, my JVM is 64 bit, as evidenced by sun.arch.data.model equalling 64.

My makefile:

CLASSPATH = ../bin

vpath %.class $(CLASSPATH)

all : jnitest.dll

jnitest.dll : jnitest.o
    g++ -m64 -Wl,--add-stdcall-alias -shared -o $@ $<

jnitest.o : jnitest.cpp jnitest.h
    g++ -m64 -I"C:\Program Files\Java\jdk1.7.0_51\include" -I"C:\Program Files\Java\jdk1.7.0_51\include\win32" -c $< -o $@

jnitest.h : net/condorcraft110/jnitest/JNITest.class
    javah -verbose -classpath $(CLASSPATH) -o jnitest.h net.condorcraft110.jnitest.JNITest

clean :
    rm jnitest.h jnitest.o jnitest.dll

JNITest.java:

package net.condorcraft110.jnitest;

public class JNITest
{
    private static native void test();

    public static void main(String[] args)
    {
        System.out.println("sun.arch.data.model = " + System.getProperty("sun.arch.data.model"));

        System.loadLibrary("jnitest");

        test();
    }
}

jnitest.h as generated by javah:

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

#ifndef _Included_net_condorcraft110_jnitest_JNITest
#define _Included_net_condorcraft110_jnitest_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     net_condorcraft110_jnitest_JNITest
 * Method:    loadPlugins
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_net_condorcraft110_jnitest_JNITest_test
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

jnitest.cpp:

using namespace std;

#include <jni.h>
#include <iostream>
#include "jnitest.h"

extern "C" JNIEXPORT void JNICALL Java_net_condorcraft110_jnitest_JNITest_test(JNIEnv *env, jclass clazz)
{
    cout << "jni test successful" << endl;
}

Anyone know why this isn't working?

Edit: java.library.path definitely points to native, as set up in an Eclipse run configuration. Edit 2: the DLL works if I compile it with VS2013, but I really don't want to tie my project to Visual Studio if I can help it.

For me, the problem was that my newly-added DLL relied on other DLLs I didn't know about. Windows helpfully went out and found a 32-bit version in my path, but was unable to load it, as my application is 64-bit.

I used Dependency Walker (there are 32 and 64-bit versions, as well as Itanium...) and Process Monitor to debug this. The long and short of it is make sure that every single DLL that your DLL pulls in is also 64-bit, and you'll be a lot happier.

One thing to watch out for is if Windows finds a 32-bit DLL of the right name it will try to load it, and in Process Monitor it will look like it's reading it successfully. Make sure to keep scrolling down!! You may find that the system discards this DLL and moves on to keep searching the path for a 64-bit version.

Update: Two other things to be aware of:

1) Old Dependency Walker can look like there are mismatches for the DLLs it loads e.g. it might find a 32-bit match first, when you really wanted a 64-bit DLL, and tell you there are CPU type mismatches. Just get the new version, and this issue goes away. Thanks to https://stackoverflow.com/a/22384936/309502 for this information.

2) Order matters when you're loading DLLs. I didn't realize I was loading two of them in the wrong order and could not figure out why it wasn't working. Check that you load the prerequisites first. :-)

Guide to JNI (Java Native Interface), JNI header file – this header file for C/C++ (include/jni.h into the JDK directory) includes all definitions of JNI elements that we may use into our� JNI is an extension to java for interfacing native C/C++ code. You should use it for the following situations: Running algorithms – with better performance (no security checks and no dynamic features) Working with pointers – for example when you need to access hardware

i also got the same kind of issue. The problem in my case was my dll was taking some 64bit dependent dll. i opened my jni dll into dependency walker, there i found the 64 bit dll. I replaced it with 32 bit. My problem got resolved.

Java Native Interface: JNI Example, JNI is an interface that allows Java to interact with code written in another language. jni.h is a C/C++ header file included with the JDK that maps Java types to� Calling Java Class Methods from C with JNI It never fails. There is some great piece of code that will save you tons of time, but it is written in Java and your project is written in C or C++. Okay, I've really only needed this a few times, but sometimes calling Java class methods from C code with JNI is the best approach.

I was initially getting Can't find dependent libraries error, to resolve which I added the DLLs in the path. But this led me to the error %1 is not a valid Win32 application at java. To resolve it all, making a static build worked for me, which compiles with: g++ -static. It adds the dependent libraries in the build itself.

Java Native Interface, I used to have the book Essential JNI. And while it is kinda dated, much of it still works today. If I recall correctly, in C, Java constructs are simply� C functions called by JNI return JNI types, an explanation of which can be found in the JNI Spec. Generally, putting "j" before a C/Java type will get you the JNI type, and in some cases they're nothing more than a typedef. A jdoublefor example is defined by typedef double jdouble;

JNI Calls different in C vs C++?, The C declarations of JNIEnv and JavaVM are different from the C++ declarations . The "jni.h" include file provides different typedefs depending� The main difference between JNI calls in C and CPP is this: C-style JNI looks like (*env)->SomeJNICall(env, param1 ) C++ style JNI looks like env->SomeJNICall(param1 ) so to convert it to CPP you need to do

JNI tips | Android NDK, Android.mk; Application.mk; Java-side Implementation; C-side Implementation. This sample guides you through hello-jni, a minimal C/C++� JNI and C ++ - UnsatisfiedLinkError I'm using JNI successfully to call some C code, however when I want to change to C++ JNI throws an UnsatisfiedLinkError whenever I try to call a method. This one works: g++ -c -Icryptopp562 -O3 -fPIC -fpermissive CI3CppEncryptionToolsImpl.cpp gcc -I$

Sample: hello-jni | Android NDK, Java Native Interface (JNI) is a framework that allows your Java code to call native applications and libraries written in languages such as C,� Java Native Interface (JNI) is a standard programming interface for writing Java native methods and embedding the Java virtual machine into native applications. The primary goal is binary compatibility of native method libraries across all Java virtual machine implementations on a given platform. JNI 6.0 API Specification

Comments
  • Did you ever figure out the issue here? I'm running into the same problem, using 64 bit gcc with cygwin.
  • @Philip I solved this. Take a look and see if your issue was similar to mine. :-)
  • I will try this when I get back to my dev machine, but thanks for answering a question as old as this!
  • Interesting! I managed to "solve" my issue by completely swapping to mingw instead of cygwin, but it'd be nice to test this out. My understanding was that cygwin-compiled applications needed to load cygwin-specific DLLs, and that the gcc option to disable this was left out of version 4+, and still hasn't been added back. I suppose the issue could be resolving to 32 bit cygwin DLLs rather than 64.
  • Dependency Walker was of great help! Thanks for the tip!