Wenn Sie einen benutzerdefinierten Klassenloader zum Laden der Klassendatei verwenden möchten, müssen Sie die Klasse java.lang.classloader erben.
Es gibt mehrere wichtige Methoden für den Klassenloader:
ProtectedClassloader (ClassloaderParent): Erstellt einen neuen Klassenlader mit dem angegebenen übergeordneten Klassenlader für Delegiervorgänge.
ProtectedFinalClass <?> Definition (StringName, Byte [] B, Intoff, Intlen): Konvertieren Sie ein Array von Bytes in eine Instanz der Klassenklasse.
ProtectedClass <?> FindClass (StringName): Finden Sie die Klasse mit dem angegebenen binären Namen.
publicClass <?> LoadClass (StringName): Laden Sie die Klasse mit dem angegebenen binären Namen.
ProtectedFinalClass <?> FindloadedClass (StringName): Wenn die java -virtuelle Maschine diesen Loader als Startlader einer Klasse mit einem bestimmten Binärnamen aufgezeichnet hat, wird die Klasse mit diesem binären Namen zurückgegeben. Ansonsten kehren Sie NULL zurück.
publicFinalClassloaderGetParent (): Gibt den legierten übergeordneten Klassenloader zurück.
ProtectedFinalvoidResolveclass (Klasse <?> C): Link zur angegebenen Klasse.
Wenn Sie dem übergeordneten Delegationsmodell folgen möchten, schreiben Sie die FindClass (StringName) -Methode neu. Wenn Sie dem übergeordneten Delegationsmodell nicht folgen möchten, schreiben Sie die Lastklasse (StringName) -Methode direkt neu.
Passen Sie die Klassenlader an, die dem übergeordneten Delegationsmodell folgen
ElterndelegateClassloader.java
Paket com.zzj.classloader; import Java.io.BytearrayoutputStream; Import Java.io.file; Import Java.io.FileInputStream; Java.io.ioxception importieren; ParentsDelegateClassLoader extends ClassLoader {private static final String EXT = ".class";private String path;public ParentsDelegateClassLoader() {path = this.getResource("").getPath();}public ParentsDelegateClassLoader(String path) {this.path = path;}@Override protected Class<?> findClass(String name) throws ClassNotFoundException {byte[] b = null;try {b = loadClassFile(name);}catch (IOException e) {e.printStackTrace();}return this.defineClass(name, b, 0, b.length);}private byte[] loadClassFile(String name) throws IOException {String classFile = getClassfile (name); {out.write (temp, 0, count);} out.close (); input.close (); retoBytearray ();} private String getClassfile (String name) {String pathname = name.replace (". Ext;} return path + file.separator + pathname + ext;}}Jetzt gibt es eine Klassendatei com/zzj/classloader/user.class unter dem Classpath ClassPath und f: // classloadtest // Bin -Verzeichnis. Der Paketname ist com.zzj.classloader. Verwenden Sie den Klassenloader ElterndelegateClassloader, um die Klasse unter f: // classloadtest // bin zu laden.
Paket com.zzj.classloader; public class app {private static final String path = "f: // classloadtest // bin"; private static final String className = "com.zzj.classloader classloader.loadClass (className); system.out.println (clazz);Ausgabe:
Klasse com.zzj.classloader.user sun.misc.launcher$appclassloader@19821f
Der Loader der Benutzerklasse ist der Systemklassenlader AppClassloader, nicht der Klassenlader, den wir selbst definieren. Tatsächlich ist es nicht die Klasse unter f: // classloadtest // bin, sondern die Klasse unter dem ClassPath. Dies ist das übergeordnete Delegationsmodell: Wenn der Elternlader der Eltern die Ladeanforderung empfängt, wird zunächst an den Lader der Elternklasse delegiert. Wenn der übergeordnete Klassenlader erfolgreich geladen wird, wird ein Klassenobjekt zurückgegeben. Wenn die Last fehlschlägt, wird der Klassenlader, der die Lastanforderung erhalten hat, geladen.
Löschen Sie die Benutzerklasse unter ClassPath, um den Lauf zu testen:
Die Klassendatei wird in Kürze geladen f: /classloadtest/Bin/com/zzj/classloader/user.class Class com.zzj.classloader.user com.zzj.classloader.parentsdelegateclassloader@61de33
Zu diesem Zeitpunkt lädt die Benutzerklasse als ElterndelegateClassloader.
Dies kann aus dem Quellcode von Classloader überprüft werden:
öffentliche Klasse <?> LoadClass (String -Name) löst classNotFoundException {return LoadClass (Name, False) aus; }Die überlastete Methode wurde genannt:
Protected Synchronisierte Klasse <?> LoadClass (String -Name, Boolean Resolve) löst ClassNotFoundException aus {// Bestimmen Sie zuerst, ob die Klasse von der aktuellen Klassenlader -Klasse c = findloadedClass (Name) geladen wurde; if (c == null) {try {if (übergeordnet! } else {// Wenn die übergeordnete Klasse leer geladen wird, ist die übergeordnete Klassenlader der Startklasse -Loader c = findbootstrapClass0 (Name); }} catch (classNotFoundException e) {// Wenn der übergeordnete Klassenloader nicht geladen wird, wird sich selbst geladen und ruft die FindClass -Methode auf! C = FindClass (Name); }} if (Resolve) {ResolVeclass (c); } return c; }Es ist ersichtlich, dass Sie, wenn Sie das übergeordnete Delegationsmodell zerstören möchten, die Methode für die LoadClass (StringName) direkt neu schreiben können.
Passen Sie Klassenlader an, die nicht dem übergeordneten Delegationsmodell folgen
NOTPARENTSDELEGATECLASSOADER.JAVA
Paket com.zzj.classloader; import Java.io.BytearrayoutputStream; Import Java.io.file; import Java.io.FileInputStream; Import Java.io.filenotFoundException; importieren java.io.ioxception; @Author Administrator * * */public class NotparentsDelegateClassloader erweitert den Classloader {private statische endgültige String ext = ".Class"; private String -Pfad; public notparentsDelegateClassloader () {path = this.getResource ("). Klasse <?> LoadClass (String -Name) löscht ClassNotFoundException {byte [] b = null; try {b = loadClassfile (name);} catch (FilenotFoundException e) {System.err.println ("Loader" + this.getClass (). Die übergeordnete Klasse Loader Return getClass (). getClassloader (). LoadClass (Name);} catch (ioException e) {System.err.println ("Loader" + this.getClass (). getName () + "Loading Class -Datei" + Name + "Fehlgeschlagen, delegiert an das übergeordnete Klassen -Lader!"). getClass (). getClassloader (). LoadClass (Name);} // Überprüfen Sie, ob die Klasse vom aktuellen Klassenloader geladen wurde (nur den aktuellen Klassenloader, nicht die übergeordnete Klasse -Loader) Class <?> clazz = findloaddClass (Name); if (Clazz! {System.out.println ("Klasse" + Name + "NICHT geladen!");} Return this.DefineClass (Name, b, 0, b.Length);} private byte [] loadClassSfile (String name) löscht IOException, FilenotFoundException {String ClassFile = GetClassFile (Name). classFile); bytearrayoutputStream out = new bytearrayoutputStream (); InputStream input = new FileInputStream (ClassFile); int count; byte [] temp = new byte [1024]; while ((count = input.Read.Read))))> -1) {Out. out.toByteArray();}private String getClassFile(String name) {String pathName = name.replace(".", File.separator);if (path.endsWith("/") || path.endsWith("//")) {return path + pathName + EXT;}return path + File.separator + pathName + EXT;}}Jetzt gibt es eine Klassendatei com/zzj/classloader/user.class unter dem Classpath ClassPath mit dem Paketnamen com.zzj.classloader, und die Benutzerklasse ist Loader NotparentsDelegateClassloader.
Paket com.zzj.classloader; public class app2 {private static final String className = "com.zzj.classloader.user"; public static void main (String [] args) Ausnahme aus der Ausnahme {notparentsDelegateClassLader classLader = new nicententsDelegateClassloader (); classloader.loadClass (className); system.out.println (clazz);Ausgabe:
Die Klassendatei /e:/myeclipse/zzjtest/webroot/web-inf/classes/com/zzj/classloader/user.class Class com.zzj.classloader.user wurde noch nicht geladen! Die Klassendatei wird bald geladen/e: /myeclipse/zzjtest/webroot/web-inf com.zzj.classloader.notParentsDelegateClassloader -Klassendatei Java.lang.Object wird nicht gefunden und wird an den übergeordneten Klassenloader delegiert!
Zu diesem Zeitpunkt ist der Lader der Benutzerklasse einen naturparentsDelegateClassloader, der nicht zuerst an die übergeordnete Klasse delegiert wird. Es wird nur an den Lader der übergeordneten Klassenlader delegiert, wenn die Last fehlschlägt. Dies ist das Gegenteil des übergeordneten Delegationsmodells.
Selbst wenn die Last ausfällt, kann sie natürlich angegeben werden, ohne an den Lader der Elternklasse zu delegieren, so dass der Klassenlastmechanismus komplexerer Netzmodelle erstellt werden kann.
Zusammenfassen
Im obigen dreht sich alles um das Codebeispiel von Java Custom Class Loader. Ich hoffe, es wird für alle hilfreich sein. Interessierte Freunde können weiterhin auf andere verwandte Themen auf dieser Website verweisen. Wenn es Mängel gibt, hinterlassen Sie bitte eine Nachricht, um darauf hinzuweisen. Vielen Dank an Freunde für Ihre Unterstützung für diese Seite!