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,如果我能帮助它的话.
对我来说,问题是我新添加的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时,顺序很重要.我没有意识到我正在以错误的顺序装载其中两个,并且无法弄清楚它为什么不起作用.检查您是否先加载先决条件.:-)