Подтвердить что ты не робот

JNI С++ DLL - "UnsatisfiedLinkError:% 1 не является допустимым приложением Win32"

Я пытаюсь на самом деле заставить JNI работать, прежде чем погрузиться в мой фактический код, но после того, как я скомпилирую 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)

У меня это немного пошло, я знаю, что это обычно вызвано попыткой загрузить 64-битную DLL с 32-разрядной JVM. Однако мой JVM имеет 64 бит, о чем свидетельствует sun.arch.data.model, равное 64.

Мой файл makefile:

CLASSPATH = ../bin

vpath %.class $(CLASSPATH)

all : jnitest.dll

jnitest.dll : jnitest.o
    g++ -m64 -Wl,--add-stdcall-alias -shared -o [email protected] $<

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 [email protected]

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: DLL работает, если я скомпилирую его с VS2013, но я действительно не хочу привязывать свой проект к Visual Studio, если я могу ему помочь.

4b9b3361

Ответ 1

Для меня проблема заключалась в том, что моя недавно добавленная DLL опиралась на другие DLL, о которых я не знал. Windows помог выйти и нашел 32-битную версию на моем пути, но не смог ее загрузить, так как мое приложение является 64-разрядным.

Я использовал Dependency Walker (есть 32 и 64-разрядные версии, а также Itanium...) и Process Monitor, чтобы отладить это. Долговременный и короткий - убедитесь, что каждая отдельная DLL, в которую входит ваша DLL, тоже 64-битная, и вы будете намного счастливее.

Одна вещь, о которой нужно помнить, - это если Windows найдет 32-битную DLL с правильным именем, она попытается загрузить ее, а в Process Monitor это будет выглядеть так, как будто она успешно ее читает. Не забудьте продолжить прокрутку! Вы можете обнаружить, что система отбрасывает эту DLL и продолжает поиск пути к 64-разрядной версии.

Update:
Две другие вещи, о которых нужно знать:

1) Уязвимость Old Dependency Walker может выглядеть как несоответствие для DLL, которые она загружает, например. он может найти 32-битное совпадение в первую очередь, когда вам действительно нужна 64-разрядная DLL, и скажу вам, что существуют несоответствия типа процессора. Просто получите новую версию, и эта проблема исчезнет. Спасибо fooobar.com/questions/706981/... за эту информацию.

2) Порядок действий при загрузке DLL. Я не понимал, что загрузил двух из них в неправильном порядке и не мог понять, почему он не работает. Убедитесь, что сначала загружаются предварительные условия.: -)

Ответ 2

у меня тоже такая же проблема. Проблема в моем случае была в том, что моя dll брала 64-битную зависимую dll. Я открыл свой JNI DLL в ходок зависимости, там я нашел 64-битную DLL. Я заменил его на 32 бит. Моя проблема была решена.

Ответ 3

Для меня создание статической сборки сработало так:

g++ -static

Он добавляет зависимые библиотеки в самой сборке.

Ответ 4

Сначала я получал сообщение " Can't find dependent libraries, для устранения которого я добавил библиотеки DLL в путь. Но это привело меня к такой же ошибке, как и вы. Чтобы решить все это, мне g++ -static создание статической сборки, которая компилируется с: g++ -static. Он добавляет зависимые библиотеки в самой сборке.