2012-04-23 13 views
5

Sono in esecuzione Windows XP. A quanto pare JNI e UnsatisfiedLinkError vanno di pari passo ... Ho notato che la maggior parte del tempo, l'errore di linker si presenta così:JNI - UnsatisfiedLinkError sul metodo nativo

java.lang.UnsatisfiedLinkError: no whatever.dll in java.library.path 

Ma non è questo il mio problema; Java può trovare la mia DLL. Ricevo un errore che mi fa pensare ho chiamato il mio metodo sbagliato:

java.lang.UnsatisfiedLinkError: NativeTest.nativemethod(lJava/lang/String;)Z 

Ho provato a guardare una serie di domande simili su StackOverflow come this one, this one, this one, this one, e this one, ma nessuno di questi metodi hanno funzionato. Ho anche trovato this thread sui forum di Ubuntu in cui sembra lo stesso identico problema che sto avendo, ma il richiedente domanda non ha detto come hanno risolto il loro problema (che fa davvero schifo). Tutte le ricerche su Google su questo mi hanno dato un errore uguale a quello di java.library.path.

Ecco il mio codice attuale.

NativeTest.java

class NativeTest 
    { 

    public static native boolean nativemethod (String arg); 

    public static void main (String[] args) 
     { 
     System.out.println(nativemethod("")); 
     System.out.println(nativemethod("012")); 
     } 

    static { System.loadLibrary("NativeTest"); } 

    } 

NativeTest.h

/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h> 
/* Header for class NativeTest */ 

#ifndef _Included_NativeTest 
#define _Included_NativeTest 
#ifdef __cplusplus 
extern "C" { 
#endif 
/* 
* Class:  NativeTest 
* Method: nativemethod 
* Signature: (Ljava/lang/String;)Z 
*/ 
JNIEXPORT jboolean JNICALL Java_NativeTest_nativemethod 
    (JNIEnv *, jclass, jstring); 

#ifdef __cplusplus 
} 
#endif 
#endif 

NativeTest.c

#include <jni.h> 
#include <windows.h> 
#include "NativeTest.h" 

JNIEXPORT jboolean JNICALL Java_NativeTest_nativemethod 
    (JNIEnv* Jenv, jclass Jref, jstring Jarg) 
    { 
    MessageBox(NULL, "text", "title", MB_OK); 
    int len = (*Jenv)->GetStringLength(Jenv, Jarg); 
    return (jboolean)(len > 5); 
    } 

In cm d.exe: (Il comando gcc è il mio miscuglio di vari comandi che ho trovato su internet.)

>javac NativeTest.java 

>javah -jni NativeTest 

>gcc -shared -I<jdk_dir>\include -I<jdk_dir>\include\win32 -oNativeTest.dll NativeTest.c -lgdi32 

>java -Djava.library.path=. NativeTest 
Exception on thread "main" java.lang.UnsatisfiedLinkError: NativeTest.nativemethod(Ljava/lang/String;)Z 
     at NativeTest.nativemethod(Native Method) 
     at NativeTest.main(NativeTest.java:8) 

>java NativeTest 
Exception on thread "main" java.lang.UnsatisfiedLinkError: NativeTest.nativemethod(Ljava/lang/String;)Z 
     at NativeTest.nativemethod(Native Method) 
     at NativeTest.main(NativeTest.java:8) 
+1

Non ho esaminato attentamente il codice, ma hai preso in considerazione l'utilizzo di JNA? Quindi non dovresti preoccuparti della scortesia di JNI. – rob

+0

Non sapevo nemmeno che esistesse JNA. Lo esaminerò. Grazie :) – nuju

+0

Qual è il nome del pacchetto che stai usando nel tuo codice java? – ioums

risposta

4

Dopo scherzare e googling per risolvere lo stesso problema per metà della giornata, ho trovato che GCC non genera DLL dove la JVM può risolvere i simboli. Ma si può passare il corretto arg di riga di comando a GCC e quindi funziona:

Vedere this MinGW post sull'argomento. Uno deve passare "-D_JNI_IMPLEMENTATION_ -Wl, - kill-at" come bandiere aggiuntive. Non so se sono necessari tutti o solo il primo bit.

+1

Lei, signore, meriti più attenzione. Ho passato mezza giornata a cercare di capirlo. Stavo per fare una domanda simile su SO quando ho visto la tua risposta. –