Classpath DLLs mittels System.load() laden:

Ulathar

Aktives Mitglied
Hallo,

ich spring hier bald im Dreieck. Ich habe ein Problem mit meinem Programm zur Laufzeit dlls zu laden.

Konkret geht es um JOGL. Ich bestimme zur Laufzeit auf welcher Plattform mein Programm ausgeführt wird (Windows, Mac oder Linux) und anschließend die Architektur (x86 oder amd64).
Basierend auf diesem "Wissen" soll mein Programm die entsprechenden Libs laden.

Soweit die Theorie.
In der Praxis bekomme ich aber einfach nicht die dlls, sos, etc geladen.

Beispielcode:

Java:
if(Settings.OS_NAME.toLowerCase().contains("windows")) {
			if(Settings.OS_ARCH.equals("amd64")) {
				try {					
					System.load(Settings.LIB_PATH + "win_x64\\jogl.dll");
					System.load(Settings.LIB_PATH + "win_x64\\jogl_awt.dll");
					System.load(Settings.LIB_PATH + "win_x64\\gluegen-rt.dll");
					System.load(Settings.LIB_PATH + "win_x64\\jogl_cg.dll");
					
					System.out.println("Success! ");
				}catch(Exception e) {
					System.out.println("Failed! ");
					e.printStackTrace(System.err);
				}
				
			}else {
//
}


        SwingUtilities.invokeLater(new Runnable() {
        	public void run() {
        		gui = new MainFrame(console);
        		gui.setVisible(true);
        	}               
        });


Analog dazu gehe ich bei allen anderen Möglichkeiten vor.
Ich sehe da einfach nicht den Fehler, aber es funktioniert einfach nicht. Die jeweiligen libs sind auch garantiert vorhanden und werden auch gefunden.
Aber im oberen Beispiel meckert der ClassLoader immer, dass die die gluegen nicht die notwendigen dependencies findet.
Ganz egal in welcher Reihenfolge ich die Libs lade.
Lasse ich die lib weg, knallt es (logischerweise) sobald ich meine JOGL Szene starte mit einer unsatisfied linker exception (could not find dll).

Wenn ich das Programm aus Eclipse heraus starte, funktioniert es einwandfrei, da ich in Eclipse die Libpfade im Projekt entsprechend gesetzt habe, nur leider wird mein "clientel" das programm NICHT aus Eclipse heraus starten 😉.

Ich versteh einfach nicht warum das nicht klappen will.
Habe auch schon versucht bei meinem Launcher (mittels launch4j generiert) den lib path zu setzen, mittels:
"-Djava.library.path="./lib/win_x64""

das funktioniert dann auch, aber NUR wenn ich das programm in einer 64bit vm unter windows ausführe. sobald ich z.b. das hier mache:
-Djava.library.path="./lib/win_x64;./lib/win_x86"

und das programm in einer x86 umgebung starten will, meckert er, da er unter x86 keine 64bit dlls laden kann (logisch).


bin für jede Anregung dankbar... so schwer kann das doch echt nicht sein -.-.
 
Versuch doch mal (ungetestet)
Java:
if(Settings.OS_ARCH.equals("amd64")) {
    try {                   
        System.setProperty("java.library.path", "./lib/win_x64");
        System.load(Settings.LIB_PATH + "win_x64\\jogl.dll");
        System.load(Settings.LIB_PATH + "win_x64\\jogl_awt.dll");
        System.load(Settings.LIB_PATH + "win_x64\\gluegen-rt.dll");
        System.load(Settings.LIB_PATH + "win_x64\\jogl_cg.dll");
        System.out.println("Success! ");
    } catch(Exception e) {
        System.out.println("Failed! ");
        e.printStackTrace(System.err);
    }
}

EDIT: Propertyname war falsch
 
ändert leider nix:

java.lang.UnsatisfiedLinkError: E:\Coding\lib\win_x64\gluegen-rt.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699)
at java.lang.Runtime.load0(Runtime.java:770)
at java.lang.System.load(System.java:1003)
at main.Main.main(Main.java:256)

und kann man den lib und classpath einer VM nicht nur zur startzeit setzen? also per commandozeile? meine da war was, dass das nicht zur laufzeit geht...

Edit:

hab auch schon versucht nach jedem System.load ein Thread.sleep(5000); zu machen da ich vermutet hatte, dass die vm etwas zeit braucht bis die dll vollständig geladen ist, aber dem scheint nicht so zu sein (erbrachte keine änderung).
 
Zuletzt bearbeitet:
Ok, es fehlt wohl noch was:

Java:
if(Settings.OS_ARCH.equals("amd64")) {
    try {                   
        changeLibraryPath("./lib/win_x64");
        System.load(Settings.LIB_PATH + "win_x64\\jogl.dll");
        System.load(Settings.LIB_PATH + "win_x64\\jogl_awt.dll");
        System.load(Settings.LIB_PATH + "win_x64\\gluegen-rt.dll");
        System.load(Settings.LIB_PATH + "win_x64\\jogl_cg.dll");
        System.out.println("Success! ");
    } catch(Exception e) {
        System.out.println("Failed! ");
        e.printStackTrace(System.err);
    }
}


Java:
void changeLibraryPath(String libraryPath)
{
        System.setProperty("java.library.path",libraryPath);
        Field fieldSysPath = ClassLoader.class.getDeclaredField("sys_paths");
        fieldSysPath.setAccessible( true );
        fieldSysPath.set( null, null );
}

Quelle mit Erklärung:
Setting “java.library.path” programmatically | Just Java
 
wenns an der MSVCR80.dll liegen würde, dürfte es auch aus Eclipse heraus nicht funktionieren.

ich mein gut, das problem ist jetzt nicht lebenswichtig, kann natürlich auch einfach diverse versionen für die jeweiligen OS releasen, aber ich fänds "schöner" wenns so ginge wie ichs mir vorstelle 😉.


Edit:

@Ariol:

hmm interessanter Ansatz, scheint zu funktionieren. Ich benötige mit dem Ansatz nicht einmal mehr die System.loads...
Aber das erklärt immer noch nicht, wieso die System.loads nicht funktionieren. Ich habe generell beim Laden von DLLs (nicht nur JOGL) exakt dieses Problem, sobald ich von dem Standartprozedere abweiche. Also die DLLs nicht mehr "neben dem JAR" liegen bzw sobald ich versuche libs manuell zu laden.
Das kann ja auch irgendwo nicht richtig sein, da es in so ca jedem Tutorial (auch in den offiziellen Sun/Oracle docs) so beschrieben steht...
 
Zuletzt bearbeitet:
Das problem ist nicht das Laden der DLLs sonder das Laden von den Abhängigkeiten dieser DLLs.

Wenn du z.B. versucht jogl_awt.dll zu laden wird dabei versucht werden deren Abhängigkeiten mitzuladen (z.B. jogl.dll).
Da Java nicht weiß wo es diese suchen soll muss der library-path entsprechend gesetzt werden.

AFAIK kann man dort wie bei der PATH-Variable einzelne Verzeichnisse auch durch ; getrennt einfügen.

Das Verhalten so ist wichtig, damit auch die gewünschte Version einer DLL geladen wird. Sonst kann Java nicht unterscheiden ob du lieber die jogl.dll aus win32 oder die aus win64 haben willst.

Hiermit kannst du übrigens herausfinden welche DLLs benötigt werden:
Dependency Walker (depends.exe) Home Page
 

Zurück
Oben