JNI - UnsatisfiedLinkError

tdc

Bekanntes Mitglied
Hi,
ich versuche gerade, ein einfaches HelloWorld-Programm mit JNI zu erstellen. Das Problem dabei ist, dass ich zurzeit beim Aufruf der nativen Mehtode folgende Fehlermeldung bekomme:
Code:
Exception in thread "main" java.lang.UnsatisfiedLinkError: jni.callnative()V
	at jni.callnative(Native Method)
	at jni.main(jni.java:5)

Mene Java-Klasse sieht so aus:
Java:
class jni {
  private native void callnative();

  public static void main(String[] args) {
    new jni().callnative();
  }

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

und meine Hello.c-Klasse:
Code:
#include <jni.h>
#include <stdio.h>

JNIEXPORT void JNICALL Java_jni_callnative(JNIEnv *env,
                                                  jobject obj)
{
   printf("HelloWorld\n");
   return;
}

und schließlich noch die Befehle zum kompilieren:
(ich wollte es erstmal über die Konsole versuchen, da es mir zurzeit noch zu umständlich erscheint, es z.B. in Eclipse einzurichten)
Code:
javac jni.java
javah -jni jni
gcc -fPIC -shared  -I/usr/local/java/include -I/usr/local/java/include/genunix -Wl,--add-stdcall-alias hello.c -lc -o libnativelib.so
export LD_LIBRARY_PATH="/home/pfad/JNITest"
java jni

Wodurch wird nun die Fehlermeldung verursacht?
 
Wenn ich das Kompilier-Script von
Code:
gcc -fPIC -shared -I/usr/local/java/include -I/usr/local/java/include/genunix hello.c -lc -o libnativelib.so
zu
Code:
gcc -Wl,-kill-at -fPIC -shared -I/usr/local/java/include -I/usr/local/java/include/genunix hello.c -lc -o libnativelib.so
ändere, erhalte ich die Fehlermeldung:
Code:
/usr/bin/ld: unrecognized option '-kill-at'
/usr/bin/ld: use the --help option for usage information
collect2: ld gab 1 als Ende-Status zurück
und danach auch wieder die UnsatisfiedLinkError-Exception. Mein gcc-Compiler scheint -kill-at wohl nicht zu kennen. Habe ich vielleicht eine falsche Version?
 
Daran sollte es nicht liegen, denn wenn ich
Code:
export LD_LIBRARY_PATH="/home/pfad/JNITest"
weglasse, wodurch der Pfad richtig gesetzt werden sollte, erhalte ich:
Code:
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
	at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1860)
	at java.lang.Runtime.loadLibrary0(Runtime.java:845)
	at java.lang.System.loadLibrary(System.java:1084)
	at jni.<clinit>(jni.java:9)
Das ist zwar auch eine UnsatisfiedLinkError-Exception, aber doch eine andere. 😉

Edit: Wenn ich es soweit richtig verstanden habe, liegt es bei mir angeblich daran, dass der C-Compiler irgendwelche zusätlichen Annotations produziert, die man mit -kill-at vermeiden kann. Bei mir existiert dieser Parameter aber in gcc scheinbar nicht.
 
Zuletzt bearbeitet:
Hey,
Die Kommandos sind nicht nötig. Laut diesem Tutorial reich alleine
Code:
gcc -shared -I/usr/local/java/include  -I/usr/local/java/include/genunix hello.c -o libhello.so
um die lib zu kompilieren.
Gruß,
Freak
[EDIT]Falls du ein OpenJDK verwendest reicht
Code:
gcc -shared -I/usr/lib/jvm/<jdk auswählen>/include -I/usr/lib/jvm/<jdk auswählen>/include/linux hello.c -o libhello.so
[/EDIT]
 
Zuletzt bearbeitet von einem Moderator:
Nebenbei, @nillehammer: Bei der ersten Fehlermeldung
Exception in thread "main" java.lang.UnsatisfiedLinkError: jni.callnative()V
hat der die lib offenbar schon gefunden. Er findet nur die Methode "jni.callnative" nicht. Wenn er die komplette Lib nicht finden würde, wäre es
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path
 
Nebenbei, @nillehammer: Bei der ersten Fehlermeldung
Exception in thread "main" java.lang.UnsatisfiedLinkError: jni.callnative()V
hat der die lib offenbar schon gefunden. Er findet nur die Methode "jni.callnative" nicht. Wenn er die komplette Lib nicht finden würde, wäre es
Exception in thread "main" java.lang.UnsatisfiedLinkError: no hello in java.library.path

Die Lösung ist die von javah erstellte Header einzubinden. Das hast du wohl vergessen.
 
Nur so als Anmerkung, weil das Problem hatte ich auch mal. Der Parameter
Code:
-Wl,-kill-at
ist nur bedingt "unwichtig". Im Normalfall ist er unwichtig, ja. Es gibt aber eine Ausnahme und diese nennt sich MinGW. Da muss der Parameter angegeben werden, sonst is nich. Warum weiß ich auch nicht, ist aber so.
 
Danke für die Hilfe!
Woran genau es lag kann ich auch nicht sagen, ein Fehler war jedenfalls die Benennung: lib**name**.so - dann funktioniert es.
 

Zurück
Oben