2015-12-05 4 views
8

Ich möchte einen Java-Klassenlader finden oder erstellen, der nur Systemklassen lädt, wobei Klassen im anwendungsdefinierten Klassenpfad ausgeschlossen werden. Mein Ziel ist es, mit diesem Klassenlader einen Klassenlader zu erstellen, der aus einer bestimmten JAR-Datei lädt und Systemklassen mithilfe des Klassenladeprogramms system-only auflöst, aber nicht die Klassen aus der JAR-Datei mit Klassen, die von meiner Anwendung definiert werden.Benötigen Sie einen Java-Klassenlader nur für System

Bis jetzt habe ich keine Möglichkeit gefunden, einen System-only-Klassenlader zu erstellen, der keine privaten APIs verwendet oder Annahmen über die Java-Implementierung macht. Siehe Code unten, der in meiner aktuellen Umgebung funktioniert, aber unerwünschte Annahmen trifft.

Wenn es keine Möglichkeit gibt, einen implementierungsunabhängigen System-only-Klassenlader zu erstellen, gibt es einen Grund, warum nicht? Ist das, was ich versuche, eine schlechte Idee zu machen?

private ClassLoader createJarClassLoader(File f) 
{ 
    ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); 
    if (systemClassLoader instanceof URLClassLoader) { 
     URLClassLoader cl = (URLClassLoader) systemClassLoader; 
     URL[] urls = cl.getURLs(); 
     List<URL> wantedURLs = new ArrayList<>(); 
     for (URL u : urls) { 
      if (isSystemURL(u)) { 
       wantedURLs.add(u); 
      } 
     } 
     try { 
      wantedURLs.add(f.toURI().toURL()); 
     } catch (MalformedURLException ex) { 
      return null; 
     } 
     return new URLClassLoader(wantedURLs.toArray(new URL[0]), null); 
    } 
    return null; 
} 

private boolean isSystemURL(URL u) 
{ 
    return u.getPath().contains("/jre/"); 
} 
+2

Warum versuchen Sie dies zu tun? Was versuchst du zu erreichen? – jtahlborn

+0

@jtahlborn Er gab seine Gründe sehr klar: "Mein Ziel ist ..." – qqilihq

+1

@qqilihq - nein, das OP beschrieb "was" er versuchte zu erreichen, nicht "warum" – jtahlborn

Antwort

1

Sie müssen den übergeordneten ClassLoader als Bootstrap ClassLoader festlegen. Rufen Sie getClassLoader() für ein java.lang.String -Objekt auf, um den Bootstrap-Klassenlader abzurufen und diesen in Ihrem ClassLoader-Konstruktor zu verwenden.

public class MyClassLoader extends URLClassLoader { 

    protected MyClassLoader(URL[] urls, ClassLoader parent) { 
     super(urls, parent); 
    } 

    static MyClassLoader getInstance(URL[] urls) { 
     ClassLoader parent = "".getClass().getClassLoader(); 
     return (new MyClassLoader(urls, parent)); 
    } 
} 

Die Darstellung des Bootstrap-Classloader ist als Implementierung dokumentiert

abhängig

Einige Implementierungen können null verwenden, um den Bootstrap Class Loader darzustellen. Diese Methode [getClassLoader] gibt in solchen Implementierungen null zurück, wenn diese Klasse vom Bootstrap-Klassenladeprogramm geladen wurde.

Derselbe Wortlaut gilt jedoch für den übergeordneten ClassLoader im ClassLoader-Konstruktor, was bedeutet, dass diese Lösung portabel ist.

+0

Obwohl es (meistens) in JDK 8 funktioniert, gibt es dort ist keine Garantie dafür, dass der Bootstrap-Klassenlader über alle Klassen in der Java-Plattform informiert ist; im modularen JDK, das für JDK9 geplant ist, wird es definitiv nicht. Die interessantere Frage ist, was Null bedeutet, wenn es an den ClassLoader-Konstruktor übergeben wird. Ich habe keine Spezifikation gefunden, was es bedeutet, aber vielleicht könnte es so definiert werden, dass es einen Klassenlader impliziert, der genau die Klassen in der Java-Plattform kennt, nicht mehr und nicht weniger. –

Verwandte Themen