La différence entre Java et les autres langages est que Java s'exécute sur la machine virtuelle Java (JVM). Cela signifie que le code compilé est enregistré dans un format indépendant de la plate-forme, plutôt que dans un format qui s'exécute sur une machine spécifique. Ce format présente de nombreuses différences importantes par rapport au format de code exécutable traditionnel. Plus précisément, contrairement à un programme C ou C++, un programme Java n'est pas un fichier exécutable indépendant, mais se compose de nombreux fichiers de classe distincts, chaque fichier de classe correspondant à une classe Java. De plus, ces fichiers de classe ne sont pas chargés en mémoire immédiatement, mais sont chargés lorsque le programme en a besoin. Un chargeur de classes est un outil utilisé dans la machine virtuelle Java pour charger des classes en mémoire. De plus, le chargeur de classes Java est également implémenté en Java. De cette façon, vous pouvez facilement créer votre propre chargeur de classes sans avoir une compréhension approfondie de la machine virtuelle Java.
Pourquoi créer un chargeur de classe ?
Maintenant que la machine virtuelle Java dispose déjà d’un chargeur de classes, devons-nous en créer d’autres nous-mêmes ? Bonne question ? Le chargeur de classes par défaut sait uniquement comment charger les classes à partir du système local. Lorsque votre programme est entièrement compilé de manière native, le chargeur de classes par défaut fonctionne généralement bien. Mais l’un des aspects les plus intéressants de Java réside dans la facilité avec laquelle il est possible de charger des classes depuis le réseau plutôt que simplement localement.
Par exemple, un navigateur peut charger des classes via un chargeur de classes personnalisé. Il existe également de nombreuses façons de charger des cours. L'une des choses les plus intéressantes à propos de Java est que vous pouvez le personnaliser simplement à partir d'un emplacement local ou réseau :
* Vérifiez automatiquement les signatures numériques avant d'exécuter du code non fiable
* Décryptez le code en fonction du mot de passe fourni par l'utilisateur
* Créez dynamiquement des classes en fonction des besoins des utilisateurs. Tout ce qui vous intéresse peut être facilement intégré à votre application sous forme de bytecode. Exemples de chargeurs de classes personnalisés si vous avez utilisé l'appletviewer JDK (Java Software Development Kit) (petit navigateur d'applications) ou autre.
Pour les navigateurs Java intégrés, vous utilisez déjà un chargeur de classe personnalisé. Lorsque Sun a lancé le langage Java pour la première fois, l'une des choses les plus passionnantes était d'observer comment Java exécutait le code téléchargé à partir d'un site Web distant. Exécuter depuis un site distant via HTTP
Le bytecode transmis par la connexion P semble un peu bizarre. Cela fonctionne car Java a la capacité d'installer des chargeurs de classes personnalisés. Le navigateur d'applets contient un chargeur de classe. Ce chargeur de classe ne trouve pas les classes Java localement, mais accède au serveur distant, charge le fichier de bytecode d'origine via HTTP, puis le convertit en classe Java dans la machine virtuelle Java. Bien sûr, les chargeurs de classes font beaucoup d'autres choses : ils bloquent les classes Java non sécurisées et empêchent les différentes applets sur différentes pages d'interférer les unes avec les autres. Echidna, un package écrit par Luke Gorrie, est un package logiciel Java ouvert qui permet d'exécuter plusieurs applications Java en toute sécurité dans une machine virtuelle Java. Il évite les interférences entre les applications en utilisant un chargeur de classe personnalisé pour donner à chaque application une copie du fichier de classe.
chargeur de classe Java :
Il existe trois chargeurs de classe par défaut en Java : le chargeur de classe d'amorçage, le chargeur de classe d'extension et le chargeur de classe système (également appelé chargeur de classe d'application).
Les chargeurs de classes sont l'une des fonctionnalités les plus puissantes de Java. Mais les développeurs oublient souvent de charger les composants par classe. Un chargeur de classe est une classe chargée de rechercher et de charger les fichiers de classe au moment de l'exécution. Java permet l'utilisation de différents chargeurs de classes, même des chargeurs de classes personnalisés.
Les programmes Java contiennent de nombreux fichiers de classe, chacun correspondant à une seule classe Java. Contrairement aux programmes C statiques, ces fichiers de classe sont chargés en mémoire une seule fois et doivent être chargés à tout moment. C'est ce qui différencie les chargeurs de classes. Il obtient des bytecodes indépendants de la plate-forme à partir de fichiers sources (généralement des fichiers .class ou .jar), puis les charge dans l'espace mémoire JVM afin qu'ils puissent être interprétés et exécutés. Par défaut, chaque classe d'une application est chargée par java.lang.ClassLoader. Puisqu’il peut être hérité, ses fonctionnalités peuvent être librement améliorées.
Chargeur de classe personnalisé
importer java.io.* ;
importer java.net.* ;
importer java.util.* ;
importer java.lang.reflect.Method ;
la classe publique CustomClassLoader étend URLClassLoader {
entrée privée FileInputStream = null ; //Flux d'entrée de fichier
private ByteArrayOutputStream out = null; //flux de sortie du tableau d'octets
private String[] url = null; //Chemin de chargement du fichier de classe
private byte[] data = null; //Code d'octet du fichier de classe
private String extensionalName = "" //Extension du fichier de classe
public CustomClassLoader (URL [] urls) lève une exception {
super(URL);
this.url = new String[urls.length];
pour (int i = 0; i < urls.length; i++) {
this.url[i] = urls[i].toURI().toString();
}
}
/*
* Analyser l'URL
*/
privé vide setFilePath() {
pour (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);
}
}
}
/*
* Obtenez le bytecode du fichier avec le nom de classe spécifié (nom du package + nom de la classe)
* @name nom Chaîne
* @octet de retour[]
*/
octet privé[] getFileData (nom de la chaîne) {
essayer {
this.setFilePath();
pour (URL de chaîne : this.url) {
Chaîne fileName = url + nom.replace('.', '/').concat(".") +
this.getExtensionalName();
input = new FileInputStream(new File(fileName));
si (entrée != null) {
casser;
}
}
out = nouveau ByteArrayOutputStream();
données = nouvel octet[1024] ;
int len = -1;
while ((len = input.read(data)) != -1) {
out.write(data, 0, len);
}
data = out.toByteArray();
} attraper (Exception e) {
e.printStackTrace();
} enfin {
essayer {
si (entrée != null)
input.close();
si (out != null)
out.close();
renvoyer des données ;
} attraper (Exception e) {
e.printStackTrace();
renvoie null ;
}
}
}
/*
* Rechercher des fichiers de classe en fonction du nom de classe spécifié
* @param nom Chaîne
* @classe de retour
*/
Classe protégée findClassByName (nom de chaîne) {
essayer {
byte[] data = this.getFileData(name);
si (données == null) {
renvoie null ;
}
return this.defineClass(name, data, 0, data.length);
} attraper (Exception e) {
e.printStackTrace();
renvoie null ;
}
}
/*
* Remplacer la méthode loadClass()
* @param nom Chaîne
* @classe de retour
*/
Classe publique loadClass (nom de la chaîne) {
Classe c = nulle ;
essayer {
c = super.loadClass(nom);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} enfin {
if (c == null) //Lorsque la méthode par défaut de la classe parent n'est pas chargée dans la classe spécifiée, utilisez une méthode personnalisée pour la trouver
c = this.findClassByName(nom);
retourner c;
}
}
chaîne publique getExtensionalName() {
renvoie le nom d'extension ;
}
public void setExtensionalName (String extensionalName) {
this.extensionalName = extensionalName ;
}
public static void main (String[] args) lève une exception {
URL[] url = new URL[] {new URL("file:e:/"}); //Ajoutez le chemin de la classe que vous souhaitez charger
//Peut être réseau ou local
CustomClassLoader csl = nouveau CustomClassLoader(url);
csl.setExtensionalName("rs");
Classe c1 = csl.loadClass("com.demo");
Objet obj = c1.newInstance();
Méthode méthode = c1.getMethod("printText", null);
méthode.invoke(obj, null);
}