Maison  >  Article  >  Java  >  Présentation des chargeurs de classes Java et du processus de chargement de classes

Présentation des chargeurs de classes Java et du processus de chargement de classes

王林
王林avant
2023-04-24 10:13:07810parcourir

1. Processus de chargement de classe

Présentation des chargeurs de classes Java et du processus de chargement de classes

Chargement

Grâce au nom complet de la classe (nom du package + nom de la classe), le fichier .class de la classe est obtenu et chargé dans le métaespace. .class文件,加载到元空间。

链接

  • 验证:检验.class文件的安全性

  • 准备:为静态类型变量分配内存并设置默认值

  • 解析:将常量池内的符号引用转换为直接引用,符号引用指向一个未被加载的类,或者未被加载类的字段或方法,那么解析将触发这个类的加载

初始化

执行类的构造器方法init()的过程,若该类具有父类,jvm会保证父类的init先执行,然后在执行子类的init

2. 类加载器

Présentation des chargeurs de classes Java et du processus de chargement de classes

启动类加载器

启动类加载器是由C/C++语言实现的,用来加载Java核心类库。启动类只加载包名为:java、javax、sun开头的类

扩展类加载器

父类加载器为启动类加载器加载以下两个目录中的类库:

  • java.ext.dirs目录

  • JDK安装目录:jre/lib/ext目录

我们就可以将我们自己的包放在以上目录下,就会自动加载进来了。

应用类加载器

父类加载器为启动类加载器,负责加载环境变量classpath或者系统属性java.class.path指定路径下的类库,是程序中默认的类加载器,我们Java程序中的类,都是由它加载完成的。

自定义类加载器

继承java.lang.ClassLoader类,重写findClass()方法 。如果没有太复杂的需求,可以直接继承URLClassLoader类,重写loadClass方法。

作用

  • 加密:Java代码可以轻易的被反编译,如果你需要把自己的代码进行加密以防止反编译,可以先将编译后的代码用某种加密算法加密,类加密后就不能再用Java的ClassLoader去加载类了,这时就需要自定义ClassLoader在加载类的时候先解密类,然后再加载。

  • 从非标准的来源加载代码:如果你的字节码是放在数据库、甚至是在云端,就可以自定义类加载器,从指定的来源加载类。

双亲委派模型

jvm对class文件采用的是按需加载的方式,当需要使用该类时,jvm才会将它的class文件加载到内存中产生class对象。在加载类的时候,是采用的双亲委派机制

  • 如果一个类加载器接收到了类加载的请求,它自己不会先去加载,会把这个请求委托给父类加载器去执行。

  • 如果父类还存在父类加载器,则继续向上委托,一直委托到启动类加载器:Bootstrap ClassLoader

  • 如果父类加载器可以完成加载任务,就返回成功结果,如果父类加载失败,就由子类自己去尝试加载,如果子类加载失败就会抛出ClassNotFoundException异常,这就是双亲委派模式

打破双亲委派模型

用途:

  • Java应用中存在着很多服务提供者接口(Service Provider Interface,SPI),这些接口允许第三方为它们提供实现,如常见的 SPI 有 JDBC、JNDI等,这些 SPI 的接口属于 Java 核心库,一般存在rt.jar包中,由Bootstrap类加载器加载。而Bootstrap类加载器无法直接加载SPI的实现类,所以需要反向委派给其他类加载器进行加载

  • 在Tomcat服务器中,存在一个服务器运行多个不同版本但同名服务的需求,所以需要打破双亲委派模型,加载多个同名类。

方法:

  • 使用上下文类加载器

  • 重写loadClass

    Lien
    Vérification : Vérifiez la sécurité du fichier .class🎜🎜
  • 🎜 Préparation :Allouez de la mémoire pour les variables de type statique et définissez les valeurs par défaut 🎜🎜
  • 🎜Analyse : Convertissez la référence de symbole dans le pool de constantes en une référence directe, et la référence du symbole pointe vers une classe A chargée inutilisée, ou un champ ou une méthode d'une classe déchargée, alors l'analyse déclenchera le chargement de cette classe🎜🎜🎜🎜initialisation🎜🎜exécution de la méthode constructeur de la classe init code>(). Si la classe A a une classe parent, <code>jvm veillera à ce que le init de la classe parent soit exécuté en premier, puis le init est exécuté. 🎜🎜2. Chargeur de classe🎜🎜<img src="https://img.php.cn/upload/article/000/465/014/168230238935730.png" alt="Le processus de chargement de classe Java et le chargeur de classe sont quoi">🎜🎜Chargeur de classe de démarrage🎜🎜Le chargeur de classe de démarrage est implémenté en langage C/C++ et est utilisé pour charger les bibliothèques de classes de base Java. La classe de démarrage ne charge que les classes dont les noms de package commencent par : java, javax et sun🎜🎜Chargeur de classe étendu🎜🎜Le chargeur de classe parent est <code>Chargeur de classe de démarrage. Chargez les bibliothèques de classes dans les deux répertoires suivants :🎜
    • 🎜java.ext.dirsDirectory🎜🎜🎜Répertoire d'installation JDK : répertoire jre/lib/ext🎜🎜🎜🎜Nous pouvons placer nos propres packages dans le répertoire ci-dessus et il sera automatiquement chargé. 🎜🎜Chargeur de classe d'application🎜🎜Le chargeur de classe parent est le Chargeur de classe de démarrage, qui est responsable du chargement du chemin de classe de la variable d'environnement ou de la propriété système java.class.path La bibliothèque de classes sous le chemin spécifié code> est le chargeur de classe par défaut du programme. Toutes les classes de notre programme Java sont chargées par celui-ci. 🎜🎜Chargeur de classe personnalisé🎜🎜Hérite de la classe <code>java.lang.ClassLoader et remplace la méthode findClass(). S'il n'y a pas d'exigences trop complexes, vous pouvez directement hériter de la classe URLClassLoader et remplacer la méthode loadClass. 🎜🎜Fonction🎜
      • 🎜Cryptage : Le code Java peut être facilement décompilé si nécessaire. Le code est crypté pour empêcher la décompilation. Vous pouvez d'abord chiffrer le code compilé avec un algorithme de chiffrement. Une fois la classe chiffrée, vous ne pouvez plus utiliser le ClassLoader de Java pour charger la classe. À ce stade, vous devez personnaliser le ClassLoader lors du chargement de la classe. la classe d'abord, puis chargez-la. 🎜🎜
      • 🎜Charger du code à partir de sources non standard : si votre bytecode est placé dans une base de données ou même dans le cloud, vous pouvez personnaliser le chargeur de classes pour charger des classes à partir de sources spécifiées. 🎜🎜🎜🎜Modèle de délégation parentale🎜🎜jvm utilise une méthode de chargement à la demande pour les fichiers de classe Lorsque la classe doit être utilisée, le jvm chargera son fichier de classe en mémoire pour générer un objet de classe. Lors du chargement des classes, le mécanisme de délégation parentale est utilisé. 🎜
        • 🎜Si un chargeur de classe reçoit une demande de chargement de classe, il ne la chargera pas en premier. déléguera cette requête au chargeur de classe parent pour exécution. 🎜🎜
        • 🎜Si la classe parent a toujours un chargeur de classe parent, continuez à déléguer vers le haut jusqu'à ce que Démarrez le chargeur de classe : Bootstrap ClassLoader🎜🎜
        • 🎜Si le chargeur de classe parent peut Après avoir terminé la tâche de chargement, un résultat réussi sera renvoyé. Si le chargement de la classe parent échoue, la sous-classe essaiera de la charger par elle-même, une exception ClassNotFoundException sera levée. Il s'agit du modèle de délégation parentale🎜🎜🎜🎜Rompre le modèle de délégation parentale🎜🎜Objectif :🎜
          • 🎜Application Java Il existe de nombreuses interfaces de fournisseurs de services (Service Provider Interface, SPI), qui permettent à des tiers de fournir des implémentations pour eux. Par exemple, les SPI courants incluent JDBC, JNDI, etc. Ces interfaces SPI appartiennent à la bibliothèque principale Java et existent généralement dans le package rt.jar, chargé par le chargeur de classe Bootstrap. Le chargeur de classe Bootstrap ne peut pas charger directement la classe d'implémentation SPI, il doit donc être délégué à d'autres chargeurs de classe pour le chargement🎜🎜
          • 🎜Dans le serveur Tomcat, il est nécessaire qu'un serveur exécute plusieurs versions différentes de services avec le même nom. Par conséquent, il est nécessaire de rompre le modèle de délégation parentale et de charger plusieurs classes avec le même nom. 🎜🎜🎜🎜Méthode : 🎜
            • 🎜Utiliser le chargeur de classe contextuelle 🎜🎜
            • 🎜Remplacer loadClassMéthode 🎜🎜🎜

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer