JNI C++ DLL - 'UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序'
在我开始使用实际代码之前,我试图让 JNI 真正工作,但是在我从 C++ 编译一个 DLL 并运行我的 Java 应用程序之后,我得到:
I am trying to actually get JNI working before I dive in with my actual code, but after I compile a DLL from C++ and run my Java application I get:
Exception in thread "main" java.lang.UnsatisfiedLinkError: <snip>workspaceJNI test
ativejnitest.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 所证明的那样.
Having Googled this for a bit, I know that this is usually caused by trying to load a 64 bit DLL with a 32 bit JVM. However, my JVM is 64 bit, as evidenced by sun.arch.data.model
equalling 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 FilesJavajdk1.7.0_51include" -I"C:Program FilesJavajdk1.7.0_51includewin32" -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:
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:
jnitest.h as generated by javah:
/* 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:
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;
}
有人知道为什么这不起作用吗?
Anyone know why this isn't working?
java.library.path
肯定指向 native
,就像在 Eclipse 运行配置中设置的那样.
编辑 2: 如果我使用 VS2013 编译 DLL,则该 DLL 可以工作,但如果我能提供帮助,我真的不想将我的项目绑定到 Visual Studio.
java.library.path
definitely points to native
, as set up in an Eclipse run configuration.
Edit 2: the DLL works if I compile it with VS2013, but I really don't want to tie my project to Visual Studio if I can help it.
推荐答案
对我来说,问题是我新添加的 DLL 依赖于我不知道的其他 DLL.Windows 在我的路径中找到了一个 32 位版本,但由于我的应用程序是 64 位,因此无法加载它.
For me, the problem was that my newly-added DLL relied on other DLLs I didn't know about. Windows helpfully went out and found a 32-bit version in my path, but was unable to load it, as my application is 64-bit.
我使用了 Dependency Walker(有 32 位和 64 位版本,还有 Itanium...) 和 进程监视器 来调试它.总而言之,确保你的 DLL 引入的每个 DLL 也是 64 位的,这样你会更开心.
I used Dependency Walker (there are 32 and 64-bit versions, as well as Itanium...) and Process Monitor to debug this. The long and short of it is make sure that every single DLL that your DLL pulls in is also 64-bit, and you'll be a lot happier.
需要注意的一点是,如果 Windows 找到一个名称正确的 32 位 DLL,它会尝试加载它,并且在 Process Monitor 中它看起来像是在成功读取它.确保继续向下滚动!!您可能会发现系统丢弃了这个 DLL 并继续搜索 64 位版本的路径.
One thing to watch out for is if Windows finds a 32-bit DLL of the right name it will try to load it, and in Process Monitor it will look like it's reading it successfully. Make sure to keep scrolling down!! You may find that the system discards this DLL and moves on to keep searching the path for a 64-bit version.
更新:
另外两件事需要注意:
Update:
Two other things to be aware of:
1) 旧的 Dependency Walker 看起来可能与其加载的 DLL 不匹配,例如当你真的想要一个 64 位 DLL 时,它可能会首先找到一个 32 位匹配,并告诉你 CPU 类型不匹配.只需获取新版本,此问题就会消失.感谢 https://stackoverflow.com/a/22384936/309502 提供此信息.
1) Old Dependency Walker can look like there are mismatches for the DLLs it loads e.g. it might find a 32-bit match first, when you really wanted a 64-bit DLL, and tell you there are CPU type mismatches. Just get the new version, and this issue goes away. Thanks to https://stackoverflow.com/a/22384936/309502 for this information.
2) 加载 DLL 时顺序很重要.我没有意识到我以错误的顺序加载其中两个,并且无法弄清楚为什么它不起作用.检查您是否首先加载了先决条件.:-)
2) Order matters when you're loading DLLs. I didn't realize I was loading two of them in the wrong order and could not figure out why it wasn't working. Check that you load the prerequisites first. :-)
相关文章