繁体   English   中英

JNI C++ DLL -“UnsatisfiedLinkError: %1 不是有效的 Win32 应用程序”

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

在深入研究实际代码之前,我试图让 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 所证明的sun.arch.data.model

我的生成文件:

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:如果我用 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类型不匹配。 刚刚获得新版本,这个问题就消失了。 感谢https://stackoverflow.com/a/22384936/309502获取此信息。

2)加载DLL时,顺序很重要。 我没有意识到我正在以错误的顺序装载其中两个,并且无法弄清楚它为什么不起作用。 检查您是否先加载先决条件。 :-)

我也遇到了同样的问题。 在我的情况下的问题是我的dll采取了一些64位依赖的DLL。 我打开我的jni dll进入依赖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 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM