2012-04-23 18 views
5

Używam systemu Windows XP. Widocznie JNI i UnsatisfiedLinkError iść w parze ... Zauważyłem, że większość czasu, błąd linkera wygląda następująco:JNI - UnsatisfiedLinkError na natywnej metodzie

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

Ale to nie mój problem; Java może znaleźć moją bibliotekę DLL. Dostaję błąd, który sprawia, że ​​myślę Nazwałem mój sposób niewłaściwy:

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

Próbowałem patrząc na szereg podobnych pytań na StackOverflow jak this one, this one, this one, this one i this one, ale żaden z tych metod zadziałało. Na forum Ubuntu znalazłem także this thread, gdzie wygląda to dokładnie tak samo, jak mam, ale pytający nie powiedział, w jaki sposób naprawili swój własny problem (który naprawdę jest do bani). Wszystkie wyszukiwania w tym serwisie Google dały mi taki sam błąd, jak błąd java.library.path.

Oto mój rzeczywisty kod.

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); 
    } 

w CM d.exe: (Komenda gcc jest moim galimatias różnych poleceń Znalazłem w internecie.)

>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

Nie przyjrzałem się uważnie Twojemu kodowi, ale czy rozważałeś zamiast tego używać JNA? Wtedy nie musiałbyś się martwić o nieprzyjazność JNI. – rob

+0

Nie wiedziałem nawet, że JNA istnieje. Przyjrzę się temu. Dzięki :) – nuju

+0

Jaka jest nazwa pakietu, którego używasz w swoim kodzie java? – ioums

Odpowiedz

4

Po aprowizacji i googlowania rozwiązać ten sam problem na pół dnia, mam odkrył, że GCC nie generuje bibliotek DLL, w których JVM może rozwiązywać symbole. Ale można przekazać prawidłowe argumenty wiersza poleceń do GCC, a następnie działa:

Zobacz this MinGW post na ten temat. Trzeba przekazać "-D_JNI_IMPLEMENTATION_-Wl, - kill-at" jako dodatkowe flagi. Nie wiem, czy wszystkie są potrzebne, czy tylko pierwszy.

+1

Proszę pana, zasługują na więcej uwagi. Spędziłem pół dnia próbując to rozgryźć. Właśnie miał zadać podobne pytanie na SO, gdy zobaczyłem twoją odpowiedź. –