2015-02-09 12 views
8

Sto cercando di far funzionare JNI prima di immergermi con il mio codice effettivo, ma dopo aver compilato una DLL da C++ ed eseguito la mia applicazione Java I get:JNI C++ DLL - 'UnsatisfiedLinkError:% 1 non è un'applicazione Win32 valida'

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) 

Avendo googled questo per un po ', so che questo di solito è causato dal tentativo di caricare una DLL a 64 bit con un 32 bit JVM. Tuttavia, la mia JVM è a 64 bit, come evidenziato da sun.arch.data.model pari a 64.

mio 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 come generato da 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; 
} 

Qualcuno sa perché questo non funziona?

Edit:java.library.path punti sicuramente a native, come impostato in una configurazione di esecuzione Eclipse.
Modifica 2: la DLL funziona se la compo con VS2013, ma io in realtà non voglio legare il mio progetto a Visual Studio se posso aiutarlo.

+0

Hai mai capito il problema qui? Sto incontrando lo stesso problema, usando gcc a 64 bit con cygwin. – Philip

+0

@Philip Ho risolto questo. Dai un'occhiata e vedi se il tuo problema era simile al mio.:-) – kmort

risposta

6

Per me, il problema era che la mia DLL appena aggiunta faceva affidamento su altre DLL che non conoscevo. Windows è uscito utilmente e ho trovato una versione a 32 bit nel mio percorso, ma non è stata in grado di caricarla, poiché la mia applicazione è a 64 bit.

Ho usato Dependency Walker (ci sono versioni a 32 e 64 bit, così come Itanium ...) e Process Monitor per eseguire il debug di questo. Il lungo e breve di esso è assicurarsi che ogni singola DLL che la tua DLL inserisce sia anche a 64 bit, e sarai molto più felice.

Una cosa a cui fare attenzione è se Windows trova una DLL a 32 bit con il nome corretto, proverà a caricarlo e in Process Monitor sembrerà che lo stia leggendo con successo. Assicurati di continuare a scorrere verso il basso !! È possibile che il sistema scarti questa DLL e prosegua per continuare a cercare nel percorso una versione a 64 bit.

Aggiornamento: altri
Due cose di essere a conoscenza di:

1) Vecchio Dependency Walker può apparire come ci sono mancate corrispondenze per le DLL che carichi per esempio potrebbe trovare prima una corrispondenza a 32 bit, quando si desidera realmente una DLL a 64 bit e si dice che ci sono delle discrepanze di tipo CPU. Prendi la nuova versione e questo problema scompare. Grazie a https://stackoverflow.com/a/22384936/309502 per queste informazioni.

2) L'ordine è importante quando si caricano DLL. Non mi rendevo conto che stavo caricando due di loro nell'ordine sbagliato e non riuscivo a capire perché non funzionava. Verifica di aver caricato prima i prerequisiti. :-)

+0

Lo proverò quando tornerò alla mia macchina dev, ma grazie per aver risposto a una domanda vecchia come questa! –

+0

Interessante! Sono riuscito a "risolvere" il mio problema scambiando completamente con mingw anziché con cygwin, ma sarebbe bello testarlo. La mia comprensione era che le applicazioni compilate da cygwin dovevano caricare DLL specifiche per cygwin e che l'opzione gcc per disabilitare questo era fuori dalla versione 4+ e non è stata ancora aggiunta. Suppongo che il problema potrebbe essere risolto con DLL Cygwin a 32 bit anziché 64. – Philip

+0

Dipendenza Walker è stato di grande aiuto! Grazie per il consiglio! –