Alle Nativen Bibliotheken auflisten, die mit System.loadLibrary geladen wurden

Thomas Darimont

Erfahrenes Mitglied
Hallo,

Java:
/**
 * 
 */
package de.tutorials;

import java.lang.reflect.Field;
import java.util.Vector;

/**
 * @author Thomas.Darimont
 * 
 */
public class ListLoadedLibraries {

    /**
     * @param args
     */
    public static void main(String[] args) throws Exception {
        Field loadedLibraryNamesField = ClassLoader.class
                .getDeclaredField("loadedLibraryNames");
        loadedLibraryNamesField.setAccessible(true);
        @SuppressWarnings("unchecked")
        Vector<String> loadedLibraryNames = (Vector<String>) loadedLibraryNamesField
                .get(null);
        for (String string : loadedLibraryNames) {
            System.out.println(string);
        }
    }

}

Setzt man obiges Beispiel über ein Eclipse Plugin in Eclipse ab so bekommt man folgende Ausgabe:
Code:
C:\Programme\Java\jdk1.6.0_01\jre\bin\zip.dll
D:\eclipse\europa-3.3\eclipse\plugins\org.eclipse.equinox.launcher.win32.win32.x86_1.0.0.v20070523\eclipse_1017a.dll
C:\Programme\Java\jdk1.6.0_01\jre\bin\net.dll
C:\Programme\Java\jdk1.6.0_01\jre\bin\nio.dll
C:\Dokumente und Einstellungen\Thomas.Darimont\workspace-europa\.metadata\.plugins\org.eclipse.pde.core\Eclipse Application\org.eclipse.osgi\bundles\890\1\.cp\swt-win32-3346.dll
C:\Dokumente und Einstellungen\Thomas.Darimont\workspace-europa\.metadata\.plugins\org.eclipse.pde.core\Eclipse Application\org.eclipse.osgi\bundles\890\1\.cp\swt-gdip-win32-3346.dll

Werden nun von anderen Plugins native Bibliotheken nachgeladen und die Auflistung erneut durchgeführt so erscheinen auch die neu dazu geladenen nativen Bibliotheken :)

Das "könnte" man nun als check verwenden ob eine bestimmte native Bibliothek schon geladen worden ist, oder nicht.

//Edit funktioniert leider nur mit dem Sun JDK.

Gruß Tom
 
Hallo Tom,

das funktioniert mit WAS (WebSphere AS) leider nicht! Hast Du vielleicht Idee, wie man mit WAS das Problem lösen könnte?

Danke im Voraus!
 
Hallo Tom,

vielen dank erstmal für die schnelle Antwort!

Unsere Applikation läuft auf WAS und verwendet IBM JDK. Wenn man die Applikation runterfährt, werden die geladene native libraries nicht richtig entladen, so dass wir eine Exception: java.lang.UnsatisfiedLinkError bekommen.
Das Problem konnten wir mit TomCat und SUN JDK lösen, so dass wir über Abfragen:
ClassLoader.class.getDeclaredField("nativeLibraries") oder
ClassLoader.class.getDeclaredField("loadedLibraryNames") die libs entladen konnten.

Und nun wie gesagt, funktioniert das Ganze mit IBM nicht :-(

Wenn Du eine Idee hättest, wäre super!

Danke, samdi
 
Wenn ich mich gerade nicht verguckt habe, geht das mit dem IBM JDK nicht, da dort im ClassLoader das Feld gar nicht existiert.
 
Richtig!
Hier sind alle Felder, die im ClassLoader vorhanden sind:

static java.lang.ClassLoader java.lang.ClassLoader.systemClassLoader
private static java.lang.ClassLoader java.lang.ClassLoader.applicationClassLoader
private static boolean java.lang.ClassLoader.initSystemClassLoader
private static boolean java.lang.ClassLoader.reflectCacheEnabled
private static boolean java.lang.ClassLoader.reflectCacheAppOnly
private static boolean java.lang.ClassLoader.reflectCacheDebug
private long java.lang.ClassLoader.vmRef
ava.lang.ClassLoader java.lang.ClassLoader.parent
private static java.lang.String[] java.lang.ClassLoader.cachedVMArgs
private static boolean java.lang.ClassLoader.checkAssertionOptions
private java.lang.Object java.lang.ClassLoader.assertionLock
private boolean java.lang.ClassLoader.defaultAssertionStatus
private java.util.Map java.lang.ClassLoader.packageAssertionStatus
private java.util.Map java.lang.ClassLoader.classAssertionStatus
private java.util.Hashtable java.lang.ClassLoader.genericRepository
private java.util.Hashtable java.lang.ClassLoader.annotationCache
private java.util.Hashtable java.lang.ClassLoader.packages
private java.lang.Object java.lang.ClassLoader.lazyInitLock
private java.util.Hashtable java.lang.ClassLoader.classSigners
private java.util.Hashtable java.lang.ClassLoader.packageSigners
private static java.security.cert.Certificate[] java.lang.ClassLoader.emptyCertificates
private java.security.ProtectionDomain java.lang.ClassLoader.defaultProtectionDomain
private final java.util.Hashtable java.lang.ClassLoader.methodCache
private final java.util.Hashtable java.lang.ClassLoader.fieldCache
private final java.util.Hashtable java.lang.ClassLoader.constructorCache
 
Hallo,

habs gerade gechecked,... die oben genannte Möglichkeit alle geladenen User-Libs auszulesen funktioniert so nicht mit dem IBM JDK (wie zeja schon angemerkt hat). ich glaube sogar, dass das so nur mit dem Sun JDK funktioniert...

Ich sehe so ohne weiteres erstmal keine (Java-Only) Möglichkeit an die geladenen dlls eines Prozesses heranzukommen...

Eine Möglichkeit für manuelles Library Management wäre IMHO die dlls über einen eigenen dedizierten (URL)ClassLoader zu laden (und wirklich nur über den!). Diesen hat man dann unter Kontrolle. Wenn dieser GC'ed wird wird auch die library freigegeben welche damit geladen wurde.

Siehe auch hier:
http://codethesis.com/tutorial.php?id=1

Eine andere Variante (Windows) wäre per ListDLL http://technet.microsoft.com/en-us/sysinternals/bb896656.aspx
die Liste der dlls für den aktuellen Prozess ermitteln und dann entsprechend verarbeiten.

Gruß Tom
 
Hallo,

leider funktioniert über CustomClassLoader nicht wirklich.
Nachdem CustomClassLoader.dispose();
und System.gc(); aufgerufen wurden,
werden die geladene dll's/prozesse nicht gekillt/entladen (sehe unter windows z.B. über Process Explorer).

Habt Ihr Idee?

Danke!
 
Zurück