Je commence tout juste à apprendre l'architecture interne de Java. J'ai compris à peu près le concept de chargement de classe qui charge les classes requises lorsque jvm
s'exécute, ClassNotFoundException
est levé lorsqu'une classe est introuvable et qu'un chargeur de classe spécifique charge les classes référencées par la classe.
Quelqu'un peut-il s'il vous plaît expliquer clairement le flux de chargement de classe, c'est-à-dire la séquence de bootstrap chargement de classe et chargement de classe défini par l'utilisateur dans l'exemple Java ci-dessous.
import Java.io.File;
public class Sample
{
public static void main(String[] args)
{
String fileName = "sample";
File file = new File(fileName);
file.isFile();
}
}
De plus, j'ai appris d'un matériau de référence que "classloader
conserve les espaces de noms des classes qu'il charge". Par espaces de noms, cela signifie-t-il les noms littéraux de la classe? Aussi quelqu'un peut-il s'il vous plaît expliquer les implications/avantages de cela?
Vous allez exécuter votre classe Sample
comme suit
> Java Sample
pour un peu de magie, consultez le résultat de-verbose:class
option et vous voyez des tonnes de lignes suivantes ..
[Opened C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Java.lang.Object from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Java.io.Serializable from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Java.lang.Comparable from C:\jdk1.6.0_14\jre\lib\rt.jar]
.
.
.
.
.
.
[Loaded Java.security.cert.Certificate from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Sample from file:/D:/tmp/]
[Loaded Java.lang.Shutdown from C:\jdk1.6.0_14\jre\lib\rt.jar]
[Loaded Java.lang.Shutdown$Lock from C:\jdk1.6.0_14\jre\lib\rt.jar]
Vous voyez un tas de classes de \jre\lib\rt.jar
sont chargés, bien avant que votre classe ne soit chargée par Bootstrap
class loader (ou Primordial). Ce sont les pré-requis pour exécuter tout programme Java chargé par Bootstrap).
Un autre ensemble de fichiers JAR est chargé par le chargeur de classe Extension
. Dans cet exemple particulier, aucune classe de lib\jre\lib\ext
donc pas chargé. Mais les chargeurs de classes d'extension sont spécifiquement chargés de charger les classes à partir de l'extension lib.
EDIT: Outre la plate-forme standard Java, Sun/Oracle fournissent également un ensemble de fichiers jar utilisés pour étendre l'API principale de la plate-forme . Les fichiers JAR placés dans le dossier d'extension lib sont automatiquement placés dans le chemin de classe et n'ont donc pas besoin d'être inclus explicitement dans ce chemin. article officiel de Nice sur le même sujet.
Enfin, votre classe Sample
est chargée par Application
class loader après Bootstrap et Extension est terminé).
Chaque fois qu'une nouvelle machine virtuelle Java est démarrée, le bootstrap classloader est chargé de charger la clé Java classes (de Java.lang
package) et d’autres classes d’exécution dans la mémoire en premier. Le chargeur de classe bootstrap) est un parent de tous les autres chargeurs de classe. Par conséquent, il est le seul à ne pas avoir de parent.
Vient ensuite le chargeur de classe d'extension. Il a le classloader bootstrap) comme parent et est responsable du chargement des classes de tous les .jar
fichiers conservés dans le Java.ext.dirs
chemin - ceux-ci sont disponibles quel que soit le chemin de classe de la machine virtuelle Java.
Le troisième et le plus important chargeur de classe issu d'un perspective du développeur est le chargeur de classe du chemin de classe système, qui est un enfant immédiat du extension classloader. Il charge les classes des répertoires et des fichiers jar spécifiés par la variable d’environnement CLASSPATH
, Java.class.path
propriété système ou -classpath
option de ligne de commande.
Espace de nom ClassLoader
Dans Java, une classe est identifiée de manière unique à l'aide de ClassLoader + Class
car la même classe peut être chargée par deux chargeurs de classes différents.
Class A loaded by ClassLoader A != Class A loaded by ClassLoader B
Comment est-ce utile?
C'est utile pour définir différentes stratégies de protection et d'accès pour différents chargeurs de classe. Prenons un exemple d'applet chargé avec un autre chargeur de classe. Vous ne voudriez pas qu'une application tierce accède à tous vos ressources. Donc, pour la sécurité, il est important de maintenir différents espaces de noms.
JVM maintient un pool d'exécution dans la zone permgen où les classes sont chargées. Chaque fois qu'une classe est référencée, le chargeur de classes par défaut trouve la classe dans le chemin de classe et la charge dans ce pool. Et ceci n'est pas spécifique aux classes définies par l'utilisateur ou aux classes fournies dans JDK. Lorsqu'une classe est référencée, elle est chargée dans la mémoire.
Les classes chargées par ClassLoader sont stockées en interne dans l'instance ClassLoader
// The classes loaded by this class loader. The only purpose of this table
// is to keep the classes from being GC'ed until the loader is GC'ed.
private final Vector<Class<?>> classes = new Vector<>();
Lorsque la classe doit être ajoutée à la mémoire, la fonction suivante est appelée:
// Invoked by the VM to record every loaded class with this loader.
void addClass(Class c) {
classes.addElement(c);
}
Vous avez trouvé un diagramme utile sur le fonctionnement des chargeurs de classes.
La machine virtuelle Java commence par la création d'une classe initiale, spécifiée de manière dépendante de l'implémentation, à l'aide de la classe bootstrap. chargeur ( §5.3.1 ). La machine virtuelle Java relie ensuite la classe initiale, l'initialise et les variables d'instance statiques qui y sont déclarées, puis appelle la méthode de classe publique void main (String []) . L'appel de cette méthode entraîne toute exécution ultérieure. L'exécution des instructions Java de la machine virtuelle constituant la méthode principale peut entraîner la liaison (et par conséquent la création) de classes et d'interfaces supplémentaires, ainsi que l'appel de méthodes supplémentaires.
lire this link
Le processus de chargement peut être vu comme une interaction entre Classloader Subsystem et la zone de mémoire de la machine virtuelle Java.
Classloader fonctionne en trois étapes générales 1.) Chargement 2.) Liaison et 3.) Initialisation.
L'interaction très basique entre Classloader Subsystem et la zone de mémoire se produit lors de la liaison (à l'exception des autres interactions!)
L'activité de liaison est subdivisée en i.) Vérifiez ii.) Préparez et iii.) Résolvez. Vérifier: est plus pour la sécurité, la compilation valide est vérifiée. A l'étape ii.) Prepare - la mémoire de la variable statique est allouée et affectée avec les valeurs par défaut. Et en
iii.) Résoudre: les références symboliques sont remplacées par les références d'origine de la "zone de méthode", qui contient des données au niveau de la classe et des variables statiques.