在尝试使用我的实际代码之前,我试图让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)
谷歌搜索了一下,我知道这通常是由于尝试使用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
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();
}
}
jnitest.h由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:
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就可以工作,但我真的我不想把我的项目绑定到Visual Studio,如果我可以提供帮助的话。
答案 0 :(得分:9)
对我来说,问题是我新添加的DLL依赖于我不知道的其他DLL。 Windows在我的路径中找到了32位版本,但无法加载它,因为我的应用程序是64位。
我使用Dependency Walker(有32位和64位版本,以及Itanium ...)和Process Monitor来调试它。它的长短是确保你的DLL所引入的每个DLL也是64位的,你会更开心。
需要注意的一件事是,如果Windows找到一个正确名称的32位DLL,它会尝试加载它,而在Process Monitor中,它看起来就像是成功读取它。确保继续向下滚动!!您可能会发现系统丢弃此DLL并继续搜索64位版本的路径。
<强>更新强>
另外两件事需要注意:
1)Old Dependency Walker看起来像它加载的DLL不匹配,例如它可能首先找到一个32位匹配,当你真的想要一个64位DLL,并告诉你有CPU类型不匹配。刚刚获得新版本,这个问题就消失了。感谢https://stackoverflow.com/a/22384936/309502获取此信息。
2)当您重新加载DLL时,顺序很重要。我没有意识到我正在以错误的顺序装载其中两个并且无法弄清楚它为什么不起作用。检查您是否先加载先决条件。 : - )
答案 1 :(得分:0)
我也遇到了同样的问题。 在我的情况下,问题是我的dll正在使用一些64bit依赖的dll。 我将我的jni dll打开到dependency walker中,在那里找到了64位dll。我将其替换为32位。 我的问题解决了。
答案 2 :(得分:0)
我最初遇到Can't find dependent libraries
错误,以解决我在路径中添加了DLL的问题。但这导致了错误%1 is not a valid Win32 application at java
。要解决所有问题,可以使用一个静态构建对我有用,该构建可以编译为:g++ -static
。它将依赖库添加到构建本身中。