JNI C++ DLL - 'UnsatisfiedLinkError:%1不是有效的Win32应用程序'

con*_* II 11 c++ java 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)
Run Code Online (Sandbox Code Playgroud)

谷歌搜索了一下,我知道这通常是由于尝试使用32位JVM加载64位DLL引起的.但是,我的JVM是64位,sun.arch.data.model相当于64位.

我的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
Run Code Online (Sandbox Code Playgroud)

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

由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
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)

任何人都知道为什么这不起作用?

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

kmo*_*ort 9

对我来说,问题是我新添加的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类型不匹配.刚刚获得新版本,这个问题就消失了.感谢/sf/answers/1566945551/获取此信息.

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