【问题标题】:JNI %1 is not a valid Win32 applicationJNI %1 不是有效的 Win32 应用程序
【发布时间】:2013-08-12 19:10:42
【问题描述】:

我正在使用 JDK 1.7_25(64 位)的 64 位 Windows 8 上运行 Netbeans,遵循使用 NetBeans 的开始 JNI (https://netbeans.org/kb/docs/cnd/beginning-jni-linux.html) 的说明

说明是针对 linux 的,但我相信 Windows 的原理是一样的(生成 .dll 文件而不是 .so,使用 JDK 中的 win32 包含等)

我安装了 Cygwin64 和 Cygwin32。使用 Cygwin64,我能够从我的 C/C++ 动态库项目中生成一个 64 位 DLL。但是,当我调用 System.load("path/to/JNITest.dll") 时,我得到:

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

据我所知,在 32 位虚拟机上加载 64 位应用程序时最常出现这种情况,但我的 netbeans.conf 指向的是 64 位 JVM。

另外,当我使用 32 位版本的 Cygwin 编译并运行时,我得到了

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

我很确定我正确地生成了 DLL 文件,它只是一个简单的 HelloWorld printf 来遵循 JNI 教程。我对 JNI 和 C 很陌生,所以我不确定从哪里开始调试。我做过的最好的尝试是尝试了 32 位和 64 位 DLL,并且我确保我的 C 编译器 (Cygwin) 是 64 位的,我的 JVM 也是。

如果有任何见解,我将不胜感激!

编辑:这里是包含的文件

=== 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();
}

=== 生成的 javah 头文件 (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");

}

编辑:

问题似乎出在 DLL 上,因为我可以很好地加载其他 64 位 DLL。我认为 Cygwin 可能是问题所在,所以我将编译器更改为 MinGW-w64。它编译得很好,并且库加载了,但现在我得到了一个新的异常:

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

多挖发现这里ClassLoader读取libs.size()的时候报错:

// 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;
    }

编辑:答案!

终于明白了。

首先,Cygwin64 出了点问题。使用不同的 64 位 C 编译器消除了 not a valid win32 application 错误。

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

Java_jnitest_JNITest_doHello

代替

Java_jnitest_Main_doHello

修改后就可以了!

(虽然我在另外 6 个小时内无法回答我自己的问题......所以 dum de dum)

【问题讨论】:

  • 查找不是您自己创建的 64 位 dll。那样有用吗?如果是这样,您的 dll 由于某种原因无效,我们稍后会讨论。
  • 是的,我在我的 dll 的 System.load 之前添加了 System.load("C:\\Windows\\System32\\aaclient.dll"),随机 64 位 dll 并且有效.不过,当我尝试加载我的时,我仍然遇到异常。老实说,我对 dll 一无所知,所以我不知道从哪里开始解释它为什么无效
  • 我无法帮助你,因为我也不知道,但现在它似乎不再是 Java 问题,而是 C/C++/Win32API/DLL 问题。
  • 所以认为它可能是 64 位 Cygwin 编译器,我下载了 MinGW64 并用它来编译 dll。这一次,库加载,但我得到:线程“主”java.lang.UnsatisfiedLinkError中的异常:jnitest.JNITest.doHello()V
  • 这似乎是一个标题问题。你看过你的方法声明和定义吗?他们把我搞糊涂了。

标签: java dll java-native-interface 64-bit unsatisfiedlinkerror


【解决方案1】:

终于明白了。

首先,Cygwin64 出了点问题。使用不同的 64 位 C 编译器消除了 not a valid win32 application 错误。

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

Java_jnitest_JNITest_doHello

代替

Java_jnitest_Main_doHello

修改后就可以了!

【讨论】:

  • 您知道 cygwin 编译器出了什么问题吗?
猜你喜欢
  • 1970-01-01
  • 2021-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
  • 2019-08-10
  • 1970-01-01
相关资源
最近更新 更多