# JNI - java.lang.UnsatisfiedLinkError



## Bob (28. Jun 2011)

Hallo,

ich habe ein kleines Problem mit der Einbindung einer DLL.
Wenn ich versuche Funktionen aus der DLL zu benutzen bekomme ich einen "UnsatisfiedLinkError". Das Einbinden / Laden der DLL scheint zu funktionieren (die Exception kommt nur, wenn ich die Funktion aus der DLL benutze).

Ich habe versucht mich an das Beispiel aus "The Java Native Interface Programmer's Guide and Specification" zu halten.

Hier mal mein Java-Code:


```
public class HelloWorld {

	private native void print();

	public static void main(String[] args) {
		new HelloWorld().print();
	}
	
	static {
      System.loadLibrary("HelloWorld");
	}

}
```

die eintsprechende Header-Datei:

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

#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif
```

und die .c-Datei:


```
#include <jni.h>
 #include <stdio.h>
 #include "HelloWorld.h"

 JNIEXPORT void JNICALL
 Java_HelloWorld_print(JNIEnv *env, jobject obj)
 {

     printf("Hello World!\n");
     return;
 }
```

Ich bekomme zur Laufzeit dann folgende Exception:

```
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.print()V
	at HelloWorld.print(Native Method)
	at HelloWorld.main(HelloWorld.java:7)
```


Kann mir jemand sagen wieso ich die Exception bekomme.

Danke & mfG
Bob

Edit: Den ClassPath hab ich natürlich gesetzt: -Djava.library.path=.\bin


----------



## tuxedo (28. Jun 2011)

Probier mal den java-library-path absolut und nicht relativ anzugeben


----------



## Bob (28. Jun 2011)

Habs probiert den Pfad absolut anzugeben. Das bringt aber die gleiche Exception.

Wenn bewusst einen falschen Pfad angebe kommt zwar noch die _UnsatisfiedLinkError_ -Exception allerdings ist die Message eine andere:

```
java.lang.UnsatisfiedLinkError: no HelloWorld in java.library.path
	at java.lang.ClassLoader.loadLibrary(Unknown Source)
	at java.lang.Runtime.loadLibrary0(Unknown Source)
	at java.lang.System.loadLibrary(Unknown Source)
	at HelloWorld.<clinit>(HelloWorld.java:11)
```

Ich geh' also davon aus, dass er die dll zumindest findet.


----------



## Marco13 (28. Jun 2011)

Ja, beim ersten hat er sie noch gefunden. Liegt die Klasse in irgendeinem Package? Ansonsten ggf. mal das loadLibrary ganz an den Anfang der Klasse packen (sollte eigentlich keinen Unterschied machen, aber ... )


----------



## Bob (28. Jun 2011)

die klasse liegt im default package.
Hab den static-Block auch an den Anfang geschoben ... hat keine Veränderungen gebracht


----------



## Marco13 (28. Jun 2011)

Ja, war auch eher hilflos rum-geraten  Sicher dass nicht irgendeine ältere DLL im Verzeichnis liegt? Beim drüberschauen sehe ich zumindest keinen Fehler, wenn's partout nicht klappt kann ich morgen abend vielleicht mal schauen, was rauskommt, wenn man das compiliert...
Wie hast du das im Moment compiliert? (OS/Compiler...)


----------



## Kr0e (28. Jun 2011)

32bit / 64 bit Problem ? Manche libs sind da eingeschränkt


----------



## Marco13 (28. Jun 2011)

Da würde eine andere Meldung kommen ("Cannot load an IA64-Library .. " oder so). Die erste Fehlermeldung deutete darauf hin, dass er die DLL findet und laden kann, aber keine passende "print"-Methode darin gefunden wurde ???:L


----------



## Bob (28. Jun 2011)

Sowas hab ich mir auch gedacht...


----------



## Kr0e (28. Jun 2011)

@Marco13:

Nein, nicht unbedingt. Ich hab das mal bei GSTreamer-Java gemerkt. Die Bindings gibt es nich für 64 bit und die Fehlermeldung war dann ähnlich, nämlich, dass er eine Methode nicht finden kann... Ich hab mich auch extremst gewundert, weil es auf einem anderen PC lief... 32 bit! 

Auch wenn es vlt in diesem Fall etwas anderes ist, kann ich deine Aussage so nicht stehen lassen 
Die in C/C++ kompilierten Dll Dateien deklarieren die Funktionen z. T. mit Hilfe des Präprozessors, sprich ein Code wird nur kompiliert, wenn das System 32bit ist. Bei solchen Sachen können durchaus Fehlermeldungen wie diese auftreten


----------



## Bob (29. Jun 2011)

hmmm .....
Ich werd nachher mal mein MinGW neuinstallieren ... vielleicht hilft das ja.


----------



## Marco13 (29. Jun 2011)

Ah, MinGW und GCC und so... da gibt's ein paar Schwierigkeiten... da muss man AFAIK irgendwie mit dem DLLTool rumpfuschen, weil die Namen der Funktionen bei Windows irgendwie nicht so ein Name*@1b42* hinten dran haben oder so (*dunkle Erinnerung*). Ich hatte mir da mal was notiert, werde mal schauen, ob ich das noch finde...


----------



## Bob (29. Jun 2011)

Auf jeden Fall erstmal danke für den Hinweis.

Kannst du mir denn einen anderen Compiler empfehlen, der das Problem nicht hat?


----------



## Marco13 (29. Jun 2011)

Ja, hab nochmal geschaut, aber ich glaube das hatte doch nicht direkt damit zu tun (war eine Mail von Anfang 2008...  ) - da gng es darum, dass man eine .lib-Datei nicht mit MinGW verwenden konnte, um eine JNI-DLL draus zu bauen.
Ich verwende üblicherweise Visual Studio (Express Edition ist Kostenlos), aber ich hab's gerade mit einer steinalten IDE (Dev-Cpp) und einem alten MinGW/GCC getestet und das hat wohl funktioniert. Kann gut sein, dass nur irgendwelche Compiler-Flags fehlen, aber welche das beim GCC sein könnten... da bin ich nicht so auf dem Laufenden (Ein Hoch auf den "Compile"-Button moderner IDEs  ). 
Welchen Compiler und welche Kommandozeilen verwendest du denn im Moment?


----------



## Bob (1. Jul 2011)

Ich habe im Moment leider keine Zeit weiter an diesem Problem zu arbeiten ... 

Ich werde mich aber auf jeden Fall bald wieder diesem Problem widmen.


----------



## Bob (10. Aug 2011)

Hallo, 
wie versprochen muss ich das Probelm jetzt wieder aufwärmen ... 

Die gute Nachricht: Inzwischen funktionieren meine erstellten dlls wieder.
Die Schlechte: Ich weiß nicht genau warum.

Ich hatte vor 4 Wochen nach dem Tip bzgl. MinGW und GCC in Verbindung mit JNI (*thx Marco13*) noch ein bisschen mit den Compiler-Optionen rumgespielt. Allerdings hat es damals trotzdem nicht funktioniert.
Auf jeden Fall funktioniert es jetzt wieder ... mal sehen wie lange noch ;-)

Hier mal vielleicht mal die Kommando-Zeile:


```
gcc -IC:\Programme\Java\jdk1.6.0_21\include -IC:\Programme\Java\jdk1.6.0_21\include\win32 -IC:\Dokumente und Einstellungen\Markus\workspace\NativHelloWorld_JavaProject\bin -O0 -g3 -Wall -c -fmessage-length=0 -oHelloWorld.o ..\HelloWorld.c
gcc -Wl,-kill-at -shared -olibNativeHelloWorld_CppProject.dll HelloWorld.o
```

Vielleicht hilft das ja noch jemandem weiter ...

Grüße und nochmal danke für die Unterstützung

Bob


----------



## Kr0e (10. Aug 2011)

Ich habe inzwischen auch damit gearbeitet und ähnlcihe Probleme gehabt. Du nutzt das hier: gcc -Wl,-kill-at!!

Das war die Lösung bzw. ich habs dann mit MSVC++ gemacht und damit gings dann direkt. Diese Option verbietet dem C COmpiler, dass der an die Funktionen so dumme @12 @8 Annotations macht. Java findet dann die Methodenrümpfe nicht mehr, da die Methoden dann z.B. ()Vprint@8 heißen etc...

Warum es jetzt auf einmal klappt kann ich dir nicht sagen, aber deine Meldung ist ein eindeutiger Hinweis:

Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.print()V
    at HelloWorld.print(Native Method)
    at HelloWorld.main(HelloWorld.java:7)

Das heißt, dass die DLL schon gefunden wurde aber die Methode eben nciht 

Gruß,

Chris


----------



## Bob (10. Aug 2011)

Danke nochmal .... Ich hoffe damit kann der Thread als "erledigt" markiert werden.


----------



## Marco13 (10. Aug 2011)

Kr0e hat gesagt.:


> Ich habe inzwischen auch damit gearbeitet und ähnlcihe Probleme gehabt. Du nutzt das hier: gcc -Wl,-kill-at!!
> 
> Das war die Lösung bzw. ich habs dann mit MSVC++ gemacht und damit gings dann direkt. Diese Option verbietet dem C COmpiler, dass der an die Funktionen so dumme @12 @8 Annotations macht. Java findet dann die Methodenrümpfe nicht mehr, da die Methoden dann z.B. ()Vprint@8 heißen etc...



Hmgrlmpf ... :autsch: genau DArum ging es in der alten Mail, die ich da erwähnt hatte - aber da ging es darum, dass ich die dann mit DLLTool, Texteditor, DEF-Dateil-Export und anderen Krämpfen so zurechgestümpert habe, dass sie funktioniert haben ... dabei hätte es ein einfaches Compile-Flag schon getan... gut zu wissen :rtfm:


----------



## Kr0e (10. Aug 2011)

Wenn du den MSVC++ Compiler nutzt, dann brauchst du das Flag komischerweise nicht, ich weiß nicht warum. Liegt nach mehreren Aussagen wohl am MinGW...


----------



## Marco13 (10. Aug 2011)

Ja, ich hatte mich da nur reingefräst, weil jemand eine Bibliothek mit minGW compilieren wollte, und das nicht ging wegen dieser fehlenden @41-Dinger. Aber ... beim zweiten Nachdenken glaube ich, dass das Problem auftrat, weil diese Dinger nicht in seiner eigenen Bibliothek gefehlt haben, sondern in einer, die er nur _verwenden_ wollte (und die vielleicht mit MSVC compiliert war), d.h. vielleicht war der K(r)ampf mit dem DLLTool und den DEF-Dateien gar nicht sooo überflüssig...


----------



## Die_ELFE (4. Sep 2012)

ist zwar schon lange her, aber vllt hilft es ja noch jemandem...

Ich habe das obige Beispiel auf nem win7 x64 Rechner getestet und bin zu dem Ergebnis gekommen, dass es nicht am MinGW liegt, sondern an der verwendeten JDK bzw JRE

Mit Version 7.03 läuft alles ohne Probleme
Mit Version 7.07 bekomme ich den LinkError

Compileraufruf

```
"C:\Program Files\Java\jdk1.7.0_03\bin\javac.exe" -classpath "D:\Workspace\test" -d "C:\Users\XXX\XXX\BDllGen\temp" "D:\Workspace\test\src\HelloWorld.java"
```


```
"C:\Program Files\Java\jdk1.7.0_03\bin\javah.exe" -jni -o "D:\Workspace\test_c\src\HelloWorld.h" -classpath "C:\Users\XXX\XXX\BDllGen\temp" "HelloWorld"
```


```
"C:\Program Files (x86)\MinGW\bin\gcc.exe" -I "C:\Program Files\Java\jdk1.7.0_03\include" -I "C:\Program Files\Java\jdk1.7.0_03\include\win32" -shared -Wl,--add-stdcall-alias -o "D:\Workspace\test\src\HelloWorld_x86.dll" "D:\Workspace\test_c\src\test_c.c"
```


```
"C:\Program Files\MinGW\bin\x86_64-w64-mingw32-gcc.exe" -I "C:\Program Files\Java\jdk1.7.0_03\include" -I "C:\Program Files\Java\jdk1.7.0_03\include\win32" -shared -Wl,--add-stdcall-alias -o "D:\Workspace\test\src\HelloWorld_x64.dll" "D:\Workspace\test_c\src\test_c.c"
```


Das würde auch erklären, warum sich das Problem bei BOB irgendwann von alleine löste.

Gruß,
Die_ELFE


----------

