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

标签 java c++ windows dll java-native-interface

在深入研究我的实际代码之前,我试图让 JNI 正常工作,但是在我从 C++ 编译 DLL 并运行我的 Java 应用程序之后,我得到:

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)

用 Google 搜索了一下,我知道这通常是由于尝试使用 32 位 JVM 加载 64 位 DLL 引起的。但是,我的 JVM 是 64 位的,sun.arch.data.model 等于 64 就证明了这一点。

我的生成文件:

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

由 javah 生成的 jnitest.h:

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

有人知道为什么这不起作用吗?

编辑 java.library.path 绝对指向 native,如在 Eclipse 运行配置中设置的那样。
编辑 2:如果我用 VS2013 编译它,DLL 可以工作,但我真的不想将我的项目绑定(bind)到 Visual Studio,如果我能帮助的话。

最佳答案

对我来说,问题在于我新添加的 DLL 依赖于我不知道的其他 DLL。 Windows 有用地退出并在我的路径中找到了一个 32 位版本,但无法加载它,因为我的应用程序是 64 位的。

我用了Dependency Walker (有 32 位和 64 位版本,还有 Itanium...)和 Process Monitor调试这个。总而言之,确保您的 DLL 引入的每个 DLL 也是 64 位的,这样您会开心很多。

需要注意的一件事是,如果 Windows 找到名称正确的 32 位 DLL,它会尝试加载它,并且在 Process Monitor 中它看起来像是在成功读取它。确保继续向下滚动!您可能会发现系统丢弃此 DLL 并继续搜索 64 位版本的路径。

更新:
需要注意的另外两件事:

1) 旧的 Dependency Walker 看起来像是它加载的 DLL 不匹配,例如它可能首先找到 32 位匹配,当你真的想要一个 64 位 DLL 时,并告诉你有 CPU 类型不匹配。只需获取新版本,此问题就会消失。感谢https://stackoverflow.com/a/22384936/309502获取此信息。

2) 加载 DLL 时顺序很重要。我没有意识到我以错误的顺序加载了其中的两个,并且无法弄清楚为什么它不起作用。检查您是否首先加载了先决条件。 :-)

关于java - JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28418014/

相关文章:

java - 基于限定符的 Android 可绘制对象处理

java - 查找字符串是否唯一

java - 如何在正在运行的应用程序中更改 log4j2 模式

c++ - cin 和赋值的区别

javascript - 函数的Setter/Getter在调用函数时将函数转换为字符串?

c++ - 对话框中的菜单命令更新处理程序

c++ - OggVorbis ov_open() 抛出访问冲突异常

Java、Hibernate、MySQL - 存储 UTC 日期时间

c++ - 为什么 std::queue::pop 不返回值。?

android - 如何使用android-ndk-r10d在windows上编译ffmpeg-2.5.3