Der Unterschied zwischen Java und anderen Sprachen besteht darin, dass Java auf der Java Virtual Machine (JVM) ausgeführt wird. Dies bedeutet, dass der kompilierte Code in einem plattformunabhängigen Format gespeichert wird und nicht in einem Format, das auf einem bestimmten Computer ausgeführt wird. Dieses Format weist viele wichtige Unterschiede zum herkömmlichen Format für ausführbaren Code auf. Insbesondere ist ein Java-Programm im Gegensatz zu einem C- oder C++-Programm keine unabhängige ausführbare Datei, sondern besteht aus vielen separaten Klassendateien, wobei jede Klassendatei einer Java-Klasse entspricht. Darüber hinaus werden diese Klassendateien nicht sofort in den Speicher geladen, sondern erst dann, wenn das Programm sie benötigt. Ein Klassenlader ist ein Tool, das in der Java Virtual Machine zum Laden von Klassen in den Speicher verwendet wird. Darüber hinaus ist auch der Java-Klassenlader in Java implementiert. Auf diese Weise können Sie ganz einfach Ihren eigenen Klassenlader erstellen, ohne über tiefgreifende Kenntnisse der Java Virtual Machine zu verfügen.
Warum einen Klassenlader erstellen?
Da die Java Virtual Machine bereits über einen Klassenlader verfügt, müssen wir dann selbst andere erstellen. Gute Frage. Der Standard-Klassenlader kann nur Klassen vom lokalen System laden. Wenn Ihr Programm vollständig nativ kompiliert ist, funktioniert der Standard-Klassenlader im Allgemeinen gut. Aber eines der aufregendsten Dinge an Java ist, wie einfach es ist, Klassen aus dem Netzwerk statt nur lokal zu laden.
Beispielsweise kann ein Browser Klassen über einen benutzerdefinierten Klassenlader laden. Es gibt auch viele Möglichkeiten, Klassen zu laden. Eines der aufregendsten Dinge an Java ist, dass Sie es nicht nur lokal oder über das Netzwerk anpassen können:
* Überprüfen Sie digitale Signaturen automatisch, bevor Sie nicht vertrauenswürdigen Code ausführen
* Entschlüsseln Sie den Code basierend auf dem vom Benutzer bereitgestellten Passwort
* Erstellen Sie dynamisch Klassen entsprechend den Benutzeranforderungen und integrieren Sie sie problemlos in Form von Bytecode in Ihre Anwendung, wenn Sie den JDK-Appletviewer (Java Software Development Kit) (kleiner Anwendungsbrowser) verwendet haben
Für eingebettete Java-Browser verwenden Sie bereits einen benutzerdefinierten Klassenlader. Als Sun zum ersten Mal die Java-Sprache veröffentlichte, war es eines der aufregendsten Dinge, zu beobachten, wie Java Code ausführte, der von einer Remote-Website heruntergeladen wurde. Von einer Remote-Site über HTTP ausführen
Der von der P-Verbindung übertragene Bytecode sieht etwas seltsam aus. Dies funktioniert, weil Java die Möglichkeit hat, benutzerdefinierte Klassenlader zu installieren. Der Applet-Browser enthält einen Klassenlader. Dieser findet keine Java-Klassen lokal, sondern greift auf den Remote-Server zu, lädt die ursprüngliche Bytecode-Datei über HTTP und konvertiert sie dann in eine Java-Klasse. Natürlich machen Klassenlader noch viele andere Dinge: Sie blockieren unsichere Java-Klassen und verhindern, dass verschiedene Applets auf verschiedenen Seiten einander stören. Echidna, ein von Luke Gorrie geschriebenes Paket, ist ein offenes Java-Softwarepaket, das die sichere Ausführung mehrerer Java-Anwendungen in einer virtuellen Java-Maschine ermöglicht. Es verhindert Interferenzen zwischen Anwendungen, indem ein benutzerdefinierter Klassenlader verwendet wird, um jeder Anwendung eine Kopie der Klassendatei zu geben.
Java-Klassenlader:
In Java gibt es standardmäßig drei Klassenlader: Bootstrap-Klassenlader, Erweiterungsklassenlader und Systemklassenlader (auch Anwendungsklassenlader genannt).
Klassenlader sind eine der leistungsstärksten Funktionen von Java. Aber Entwickler vergessen oft, Komponenten in Klassen zu laden. Ein Klassenlader ist eine Klasse, die für das Suchen und Laden von Klassendateien zur Laufzeit verantwortlich ist. Java ermöglicht die Verwendung verschiedener Klassenlader, sogar benutzerdefinierter Klassenlader.
Java-Programme enthalten viele Klassendateien, die jeweils einer einzelnen Java-Klasse entsprechen. Im Gegensatz zu statischen C-Programmen werden diese Klassendateien einmal in den Speicher geladen und müssen jederzeit geladen werden. Das ist es, was Klassenlader anders macht. Es ruft plattformunabhängige Bytecodes aus Quelldateien (normalerweise .class- oder .jar-Dateien) ab und lädt sie dann in den JVM-Speicherbereich, damit sie interpretiert und ausgeführt werden können. Standardmäßig wird jede Klasse einer Anwendung von java.lang.ClassLoader geladen. Da es vererbbar ist, kann seine Funktionalität frei erweitert werden.
Benutzerdefinierter Klassenlader
java.io.* importieren;
java.net importieren.*;
import java.util.*;
import java.lang.reflect.Method;
öffentliche Klasse CustomClassLoader erweitert URLClassLoader {
private FileInputStream input = null; //Dateieingabestream
private ByteArrayOutputStream out = null; //Byte-Array-Ausgabestream
private String[] url = null; //Ladepfad der Klassendatei
private byte[] data = null; //Klassendatei-Bytecode
private String extensionalName = ""; //Klassendateierweiterung
public CustomClassLoader(URL[] urls) löst eine Ausnahme aus{
super(URLs);
this.url = new String[urls.length];
for (int i = 0; i < urls.length; i++) {
this.url[i] = urls[i].toURI().toString();
}
}
/*
* URL analysieren
*/
private void setFilePath() {
for (int i = 0; i < this.url.length; i++) {
if (this.url[i].substring(0,4).toLowerCase().equals("file") == true) {
this.url[i] = this.url[i].substring(5);
}
}
}
/*
* Rufen Sie den Bytecode der Datei mit dem angegebenen Klassennamen ab (Paketname + Klassenname).
* @name name String
* @return byte[]
*/
privates Byte[] getFileData(String name) {
versuchen {
this.setFilePath();
for (String-URL: this.url) {
String fileName = url + name.replace('.', '/').concat(".") +
this.getExtensionalName();
input = new FileInputStream(new File(fileName));
if (Eingabe != null) {
brechen;
}
}
out = new ByteArrayOutputStream();
Daten = neues Byte[1024];
int len = -1;
while ((len = input.read(data)) != -1) {
out.write(data, 0, len);
}
data = out.toByteArray();
} Catch (Ausnahme e) {
e.printStackTrace();
} Endlich {
versuchen {
if (Eingabe != null)
input.close();
if (out != null)
out.close();
Rückgabedaten;
} Catch (Ausnahme e) {
e.printStackTrace();
null zurückgeben;
}
}
}
/*
* Durchsuchen Sie Klassendateien basierend auf dem angegebenen Klassennamen
* @param name String
* @return-Klasse
*/
protected Class findClassByName(String name) {
versuchen {
byte[] data = this.getFileData(name);
if (data == null) {
null zurückgeben;
}
return this.defineClass(name, data, 0, data.length);
} Catch (Ausnahme e) {
e.printStackTrace();
null zurückgeben;
}
}
/*
* LoadClass()-Methode überschreiben
* @param name String
* @return-Klasse
*/
öffentliche Klasse loadClass(String name) {
Klasse c = null;
versuchen {
c = super.loadClass(name);
} Catch (ClassNotFoundException e) {
e.printStackTrace();
} Endlich {
if (c == null) // Wenn die Standardmethode der übergeordneten Klasse nicht in die angegebene Klasse geladen wird, verwenden Sie eine benutzerdefinierte Methode, um sie zu finden
c = this.findClassByName(name);
return c;
}
}
öffentlicher String getExtensionalName() {
return extensionalName;
}
public void setExtensionalName(String extensionalName) {
this.extensionalName = extensionalName;
}
public static void main(String[] args) löst eine Ausnahme aus {
URL[] url = new URL[] {new URL("file:e:/")}; //Fügen Sie den Pfad zu der Klasse hinzu, die Sie laden möchten
//Kann Netzwerk oder lokal sein
CustomClassLoader csl = new CustomClassLoader(url);
csl.setExtensionalName("rs");
Klasse c1 = csl.loadClass("com.demo");
Objekt obj = c1.newInstance();
Methode method = c1.getMethod("printText", null);
method.invoke(obj, null);
}