JNI C++ DLL - 'UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序'
Posted
技术标签:
【中文标题】JNI C++ DLL - \'UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序\'【英文标题】:JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application'JNI C++ DLL - 'UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序' 【发布时间】:2015-02-09 19:47:37 【问题描述】:在我开始使用实际代码之前,我试图让 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:如果我编译,DLL 可以工作VS2013,但如果我能提供帮助,我真的不想将我的项目绑定到 Visual Studio。
【问题讨论】:
你有没有发现这里的问题?我遇到了同样的问题,使用 64 位 gcc 和 cygwin。 @Philip 我解决了这个问题。看看你的问题是否和我的类似。 :-) 【参考方案1】:对我来说,问题在于我新添加的 DLL 依赖于我不知道的其他 DLL。 Windows 在我的路径中找到了一个 32 位版本,但由于我的应用程序是 64 位,因此无法加载它。
我使用Dependency Walker(有 32 位和 64 位版本,以及 Itanium...)和Process Monitor 来调试它。总而言之,确保你的 DLL 引入的每个 DLL 也是 64 位的,这样你会更开心。
需要注意的一点是,如果 Windows 找到了一个名称正确的 32 位 DLL,它会尝试加载它,并且在进程监视器中它看起来像是在成功读取它。确保继续向下滚动!!您可能会发现系统丢弃了这个 DLL 并继续搜索 64 位版本的路径。
更新: 另外两件事需要注意:
1) 旧的 Dependency Walker 看起来可能与其加载的 DLL 不匹配,例如当你真的想要一个 64 位 DLL 时,它可能会首先找到一个 32 位匹配,并告诉你 CPU 类型不匹配。只需获取新版本,此问题就会消失。感谢 https://***.com/a/22384936/309502 提供此信息。
2) 加载 DLL 时顺序很重要。我没有意识到我以错误的顺序加载其中两个,并且无法弄清楚为什么它不起作用。检查您是否首先加载了先决条件。 :-)
【讨论】:
当我回到我的开发机器时我会试试这个,但感谢你回答这么久的问题! 有趣!我设法通过完全切换到 mingw 而不是 cygwin 来“解决”我的问题,但最好测试一下。我的理解是 cygwin 编译的应用程序需要加载特定于 cygwin 的 DLL,并且禁用此功能的 gcc 选项被排除在版本 4+ 之外,并且仍然没有被添加回来。我想这个问题可能解决了 32 位 cygwin DLL 而不是 64。 Dependency Walker 帮了大忙!感谢您的提示!【参考方案2】:我最初收到Can't find dependent libraries
错误,为了解决这个问题,我在路径中添加了 DLL。但这导致我出现错误%1 is not a valid Win32 application at java
。为了解决这一切,制作一个静态构建对我有用,它编译为:g++ -static
。它在构建本身中添加依赖库。
【讨论】:
【参考方案3】:我也遇到了同样的问题。 我的问题是我的 dll 占用了一些 64 位相关的 dll。 我将我的 jni dll 打开到依赖 walker 中,在那里我找到了 64 位 dll。我用32位替换它。 我的问题得到了解决。
【讨论】:
【参考方案4】:我通过将这些 .dll 文件的列表从 Win64_x64 复制到应用程序的 bin/main 目录中解决了我的问题,应用程序运行成功:
NBiometricClient.dll
NBiometrics.dll
NCore.dll
NDevices.dll
NLicensing.dll
NMedia.dll
NMediaProc.dll
NMMAbisClient.dll
【讨论】:
以上是关于JNI C++ DLL - 'UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序'的主要内容,如果未能解决你的问题,请参考以下文章
C++调用JVM.dll运行Java程序,JNI实战简例,精简JRE实战
177Java利用JNI调用C++编写的DLL,连接海康人脸抓拍机,实现人脸库全量更新。
177Java利用JNI调用C++编写的DLL,连接海康人脸抓拍机,实现人脸库全量更新。
177Java利用JNI调用C++编写的DLL,连接海康人脸抓拍机,实现人脸库全量更新。