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,连接海康人脸抓拍机,实现人脸库全量更新。

178Java利用JNI调用C++编写的DLL,连接海康明眸门禁机,实现人脸库全量更新。

178Java利用JNI调用C++编写的DLL,连接海康明眸门禁机,实现人脸库全量更新。