JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application'

JNI C++ DLL - 'UnsatisfiedLinkError: %1 is not a valid Win32 application'

本文关键字:not application Win32 is valid UnsatisfiedLinkError DLL C++ JNI      更新时间:2023-10-16

在深入实际代码之前,我试图让JNI真正工作,但在从C++编译DLL并运行Java应用程序后,我得到:

Exception in thread "main" java.lang.UnsatisfiedLinkError: <snip>workspaceJNI testnativejnitest.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就证明了这一点。

我的生成文件:

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 FilesJavajdk1.7.0_51include" -I"C:Program FilesJavajdk1.7.0_51includewin32" -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;
}

有人知道为什么不起作用吗?

Edit:java.library.path明确指向native,这是在Eclipse运行配置中设置的
编辑2:如果我用VS2013编译DLL,它就可以工作,但如果可以的话,我真的不想把我的项目与Visual Studio联系起来。

对我来说,问题是我新添加的DLL依赖于我不知道的其他DLL。Windows很有帮助地在我的路径中找到了一个32位版本,但无法加载,因为我的应用程序是64位的。

我使用了Dependency Walker(有32位和64位版本,还有安腾…)和Process Monitor来调试它。总之,确保你的DLL中的每一个DLL都是64位的,你会更快乐。

需要注意的一件事是,如果Windows找到一个名称正确的32位DLL,它将尝试加载它,并且在进程监视器中,它看起来像是成功读取了它。请确保继续向下滚动!!您可能会发现系统会丢弃此DLL,并继续在路径中搜索64位版本。

更新:
另外两件事需要注意:

1) Old Dependency Walker加载的DLL可能看起来不匹配,例如,当你真的想要一个64位DLL时,它可能会先找到一个32位匹配,并告诉你CPU类型不匹配。只要得到新版本,这个问题就会消失。幸亏https://stackoverflow.com/a/22384936/309502以获取此信息。

2) 加载DLL时,顺序很重要。我没有意识到我以错误的顺序装载了其中两个,也不明白为什么它不起作用。请检查是否先加载先决条件。:-)

我最初得到Can't find dependent libraries错误,为了解决这个问题,我在路径中添加了DLL。但这导致了错误%1 is not a valid Win32 application at java。为了解决这一切,制作一个静态构建对我来说很有效,它使用:g++ -static编译。它在构建本身中添加依赖库。

我也遇到了同样的问题。我的问题是我的dll占用了一些64位的依赖dll。我把我的jni dll打开到dependencywalker中,在那里我找到了64位dll。我把它换成了32位。我的问题解决了。

我通过将这些.dll文件的列表从Win64_x64复制到应用程序的bin/main目录来解决我的问题,并且应用程序成功运行:

NBiometricClient.dll
NBiometrics.dll
NCore.dll
NDevices.dll
NLicensing.dll
NMedia.dll
NMediaProc.dll
NMMAbisClient.dll 
相关文章: