在深入研究我的实际代码之前,我试图让 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/