且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

JNI%1不是有效的Win32应用程序

更新时间:2022-10-20 10:57:03

终于找到它了。

首先,什么是错与Cygwin64。使用不同的64位C编译器摆脱了不是有效的Win32应用程序错误的。

其次,我JNITest.c文件的方法签名是不正确的。它应该是:

  Java_jnitest_JNITest_doHello
 

相反

  Java_jnitest_Main_doHello
 

改变这种后,它的作品!

I'm running Netbeans on 64-bit Windows 8, with JDK 1.7_25 (64-bit), following the instructions for the Beginning JNI with NetBeans (https://netbeans.org/kb/docs/cnd/beginning-jni-linux.html)

The instructions are for linux, but the principle is the same for Windows I believe (generating a .dll file instead of .so, using win32 includes in the JDK, etc)

I have Cygwin64 installed as well as Cygwin32. Using Cygwin64, I'm able to generate a 64-bit DLL from my C/C++ Dynamic Library project. However, when I call System.load("path/to/JNITest.dll"), I get:

Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Andrew\Documents\NetBeansProjects\JNITestLib\dist\JNITest.dll: %1 is not a valid Win32 application
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary1(ClassLoader.java:1957)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1882)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1843)
    at java.lang.Runtime.load0(Runtime.java:795)
    at java.lang.System.load(System.java:1061)
    at jnitest.JNITest.main(JNITest.java:8)
Java Result: 1

From what I gather, this is most often the case when loading a 64-bit application on a 32-bit virtual machine, but my netbeans.conf is pointing to a 64-bit JVM.

Additionally, when I use the 32-bit version of Cygwin to compile things and run, I get

Can't load IA 32-bit .dll on a AMD 64-bit platform

I'm pretty sure I'm correctly generating the DLL file, it's just a simple HelloWorld printf to follow the JNI tutorial. I'm very new to JNI and C, so I'm not really sure where to start debugging. The best I've done is tried both 32 and 64-bit DLLs, and I've made sure my C compiler (Cygwin) is 64-bit, and my JVM is too.

I'd appreciate any insight!

Edit: Here are the included files

=== Java (JNITest.java) ===

package jnitest;

public class JNITest {

    public static void main(String[] args) {
        System.out.println("JVM: " + System.getProperty("sun.arch.data.model"));
        System.load("C:\\Users\\Andrew\\Documents\\NetBeansProjects\\JNITestLib\\dist\\JNITest.dll");

        new JNITest().doHello();
    }

    public native void doHello();
}

=== Generated javah header (jnitest_JNITest.h) ===

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

#ifndef _Included_jnitest_JNITest
#define _Included_jnitest_JNITest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     jnitest_JNITest
 * Method:    doHello
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_jnitest_JNITest_doHello
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

=== C (JNITest.c) ===

#include <jni.h>
#include "jnitest_JNITest.h"

JNIEXPORT void JNICALL Java_jnidemojava_Main_nativePrint
        (JNIEnv *env, jobject obj) 
{
    printf("\nHello World from C\n");

}

Edit:

The problem seems to be with the DLL, since I can load other 64-bit DLLs just fine. I thought that Cygwin might be the problem, so I changed my compiler to MinGW-w64. It compiled fine, and the library loads, but now I get a new exception:

Exception in thread "main" java.lang.UnsatisfiedLinkError: jnitest.JNITest.doHello()V
    at jnitest.JNITest.doHello(Native Method)
    at jnitest.JNITest.main(JNITest.java:10)
Java Result: 1

Some more digging found that the error is thrown when ClassLoader reads libs.size() here:

// Invoked in the VM class linking code.
    static long findNative(ClassLoader loader, String name) {
        Vector<NativeLibrary> libs =
            loader != null ? loader.nativeLibraries : systemNativeLibraries;
        synchronized (libs) {
            int size = libs.size();
            for (int i = 0; i < size; i++) {
                NativeLibrary lib = libs.elementAt(i);
                long entry = lib.find(name);
                if (entry != 0)
                    return entry;
            }
        }
        return 0;
    }

Edit: ANSWERS!

Finally figured it out.

Firstly, something was wrong with Cygwin64. Using a different 64-bit C compiler got rid of the not a valid win32 application error.

Secondly, my JNITest.c file's method signature was incorrect. It should have been:

Java_jnitest_JNITest_doHello

Instead of

Java_jnitest_Main_doHello

After changing that, it works!

(though I can't answer my own question for another 6 hours... so dum de dum)

Finally figured it out.

Firstly, something was wrong with Cygwin64. Using a different 64-bit C compiler got rid of the not a valid win32 application error.

Secondly, my JNITest.c file's method signature was incorrect. It should have been:

Java_jnitest_JNITest_doHello

Instead of

Java_jnitest_Main_doHello

After changing that, it works!