JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application'
JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application'
在我深入研究我的实际代码之前,我试图让 JNI 真正工作,但是在我从 C++ 和 运行 我的 Java 应用程序编译 DLL 之后,我得到:
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();
}
}
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如果我能帮上忙。
对我来说,问题是我新添加的 DLL 依赖于我不知道的其他 DLL。 Windows 帮忙出去,在我的路径中找到了一个 32 位版本,但无法加载它,因为我的应用程序是 64 位的。
我用 Dependency Walker (there are 32 and 64-bit versions, as well as Itanium...) and Process Monitor 来调试它。总而言之,确保您的 DLL 引入的每个 DLL 也是 64 位的,这样您就会开心很多。
需要注意的一件事是,如果 Windows 找到名称正确的 32 位 DLL,它将尝试加载它,并且在 Process Monitor 中它看起来像是在成功读取它。确保继续向下滚动!您可能会发现系统丢弃此 DLL 并继续搜索 64 位版本的路径。
更新:
还有两件事需要注意:
1) 旧的 Dependency Walker 看起来像是它加载的 DLL 不匹配,例如它可能首先找到一个 32 位匹配,当你真的想要一个 64 位 DLL 时,并告诉你有 CPU 类型不匹配。只需获取新版本,此问题就会消失。感谢 提供此信息。
2) 加载 DLL 时顺序很重要。我没有意识到我以错误的顺序加载了其中的两个,并且无法弄清楚为什么它不起作用。检查您是否首先加载了先决条件。 :-)
我也遇到了同样的问题。
我的问题是我的 dll 正在使用一些 64 位依赖的 dll。
我将我的 jni dll 打开到 dependency walker,在那里我找到了 64 位 dll。我用 32 位替换了它。
我的问题已经解决了。
我最初收到 Can't find dependent libraries
错误,为了解决这个问题,我在路径中添加了 DLL。但这导致我出现错误 %1 is not a valid Win32 application at java
。为了解决这一切,使静态构建对我有用,它编译为:g++ -static
。它在构建本身中添加了依赖库。
我通过将这些 .dll 文件的列表从 Win64_x64 复制到应用程序的 bin/main 目录来解决我的问题,应用程序成功运行:
NBiometricClient.dll
NBiometrics.dll
NCore.dll
NDevices.dll
NLicensing.dll
NMedia.dll
NMediaProc.dll
NMMAbisClient.dll
在我深入研究我的实际代码之前,我试图让 JNI 真正工作,但是在我从 C++ 和 运行 我的 Java 应用程序编译 DLL 之后,我得到:
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();
}
}
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如果我能帮上忙。
对我来说,问题是我新添加的 DLL 依赖于我不知道的其他 DLL。 Windows 帮忙出去,在我的路径中找到了一个 32 位版本,但无法加载它,因为我的应用程序是 64 位的。
我用 Dependency Walker (there are 32 and 64-bit versions, as well as Itanium...) and Process Monitor 来调试它。总而言之,确保您的 DLL 引入的每个 DLL 也是 64 位的,这样您就会开心很多。
需要注意的一件事是,如果 Windows 找到名称正确的 32 位 DLL,它将尝试加载它,并且在 Process Monitor 中它看起来像是在成功读取它。确保继续向下滚动!您可能会发现系统丢弃此 DLL 并继续搜索 64 位版本的路径。
更新:
还有两件事需要注意:
1) 旧的 Dependency Walker 看起来像是它加载的 DLL 不匹配,例如它可能首先找到一个 32 位匹配,当你真的想要一个 64 位 DLL 时,并告诉你有 CPU 类型不匹配。只需获取新版本,此问题就会消失。感谢 提供此信息。
2) 加载 DLL 时顺序很重要。我没有意识到我以错误的顺序加载了其中的两个,并且无法弄清楚为什么它不起作用。检查您是否首先加载了先决条件。 :-)
我也遇到了同样的问题。 我的问题是我的 dll 正在使用一些 64 位依赖的 dll。 我将我的 jni dll 打开到 dependency walker,在那里我找到了 64 位 dll。我用 32 位替换了它。 我的问题已经解决了。
我最初收到 Can't find dependent libraries
错误,为了解决这个问题,我在路径中添加了 DLL。但这导致我出现错误 %1 is not a valid Win32 application at java
。为了解决这一切,使静态构建对我有用,它编译为:g++ -static
。它在构建本身中添加了依赖库。
我通过将这些 .dll 文件的列表从 Win64_x64 复制到应用程序的 bin/main 目录来解决我的问题,应用程序成功运行:
NBiometricClient.dll
NBiometrics.dll
NCore.dll
NDevices.dll
NLicensing.dll
NMedia.dll
NMediaProc.dll
NMMAbisClient.dll