Parler de la première partie du processus de chargement de classe

1. Initialisation du chargement de classe

  1. Chargement

    Charger un fichier de classe en mémoire

  2. Mise en relation

    1. Vérification

      Vérifiez que le caractère du fichier de classe ne répond pas à la norme de fichier de classe

    2. Préparation

      Attribuez des valeurs par défaut aux variables statiques static int count = 10;

      Dans cette étape, nombre = 0 valeur par défaut

    3. Résolution

      Les références de symboles sont converties en adresses mémoire accessibles directement

  3. Initialisation

    Affectation de variable statique à la valeur initiale

    Parler de la première partie du processus de chargement de classe

2. Chargeur de classe

1. JVM est chargé dynamiquement à la demande et adopte un mécanisme de délégation parent

Utilisez getClassLoader pour obtenir le chargeur de classe. S'il est Null, il s'agit du chargeur de classe BootStrap car il est implémenté en C ++ et il n'y a pas de classe correspondante.

Les classes que nous écrivons habituellement sont sous le chemin de classe, elles sont donc chargées par le chargeur de classe App

Remarque: ces quatre chargeurs de classe n'ont pas de relation d'héritage mais une relation séquentielle

Le chargeur parent n'est pas la classe parente, il dit simplement qu'il ne peut pas être chargé par lui-même, donc il est transféré au niveau supérieur pour être chargé

Il ne s'agit pas d'une relation d'héritage, comment sont-ils entrés en contact? Utilisez une combinaison ~~

Parler de la première partie du processus de chargement de classe

2. Le diagramme de l'étape 1 n'illustre-t-il pas la tâche des parents? Je vais vous donner une image pour vous faire comprendre la mission des parents

Non, pourquoi devrais-je utiliser des images? Permettez-moi de décrire en une phrase: classLoader trouve dans son propre cache si la classe XX a été chargée, sinon, trouve son chargeur de classe parent, et le chargeur de classe parent trouve dans son propre cache s'il a déjà été chargé Classe XX, s'il est trouvé , retourne, s'il n'est pas trouvé, puis trouve le chargeur de classe parent, jusqu'à BootStrap, s'il n'est pas trouvé dans le cache, puis regarde en arrière depuis le chargeur de classe parent, le chargeur parent demande à votre fils de voir de quoi vous êtes responsable Y a-t-il une telle classe dans le package jar? Si tel est le cas, vous pouvez la charger dans la mémoire. Sinon, vous pouvez consulter le chargeur de classe de votre fils. Vérifiez-le tout le temps et voir si le plus petit chargeur de classe est renvoyé à la fin , ou Si vous ne le trouvez pas, lancez une exception. ClassNotFoundException

J'ai quand même succombé à l'image ci-dessus.

Parler de la première partie du processus de chargement de classe

/**
 * @author 木子的昼夜
 */
public class MyClassLoaderTest {
    public static void main(String[] args) throws ClassNotFoundException {
        MyClassLoaderTest.class.getClassLoader().loadClass("classtest.MyClassLoaderTest");
    }
}

// ClassLoader#loadClass
public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
} 
protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
 {      
     // 肯定是要上锁的 不然加载冲了咋个办呢?
     synchronized (getClassLoadingLock(name)) {
         // First, check if the class has already been loaded
         // 首先,判断这个类是否已经加载到当前层级内存了 
         Class<?> c = findLoadedClass(name);
         //  如果当前层级内存没有 
         if (c == null) {
             long t0 = System.nanoTime();
             try {
                 if (parent != null) {
                     // 如果还有父级 那就在上一层的缓存里找 
                     c = parent.loadClass(name, false);
                 } else {
                     // 如果没有了 那就是最后一层了 在自己的管辖范围 找 
                     c = findBootstrapClassOrNull(name);
                 }
             } catch (ClassNotFoundException e) {
                 // ClassNotFoundException thrown if class not found
                 // from the non-null parent class loader
             }

             // 上级一直没有找到 那就只能找自己负责的范围了
             if (c == null) {
                 // If still not found, then invoke findClass in order
                 // to find the class.
                 // 如果还是没有 那就往下一级 接着在负责范围找 
                 long t1 = System.nanoTime();
                 c = findClass(name);

                 // this is the defining class loader; record the stats
                 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                 sun.misc.PerfCounter.getFindClasses().increment();
             }
         }
         if (resolve) {
             resolveClass(c);
         }
         return c;
     }
 }

Modèle de conception: méthode de modèle de fonction de crochet

3. Comment se passe-t-il lorsqu'un fichier de classe est chargé en mémoire?

Parler de la première partie du processus de chargement de classe

4. GetClassLoader () qui veut savoir quel chargeur de classe est chargé en mémoire par une certaine classe

System.out.println(String.class.getClassLoader());
// null --> BootStrap类加载器
System.out.println(sun.awt.HKSCS.class.getClassLoader());
// null --> BootStrap类加载器
       System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());
// sun.misc.Launcher$ExtClassLoader@1d44bcfa --> Ext
System.out.println(ClassLoaderTest.class.getClassLoader());
// sun.misc.Launcher$AppClassLoader@18b4aac2--> App

5. Pourquoi les parents délèguent-ils

  1. Par sécurité, s'il n'y a pas de délégation parente, recherchez la classe directement à partir du chargeur de classe personnalisé (le problème principal)

    Parler de la première partie du processus de chargement de classe

(1) Si je personnalise un java.lang.String ici,
j'écris un script de minage dans la classe String

(2) Ensuite, Xiaoyueyue a téléchargé ma bibliothèque pour l'utiliser!

Il a utilisé String, il pensait que c'était une classe jdk, mais j'ai prédit sa prédiction. Cette classe String est déjà la mienne et contrôlée par moi

(3) La délégation parentale peut éviter ce problème, car le système ira toujours à la couche supérieure pour voir s'il y a cette classe parce que la couche supérieure l'a, donc il n'utilisera pas la classe String que j'ai définie.

  1. Si le calque parent est chargé, je n’ai pas à le charger, puis le chargement est un gaspillage de ressources (problème secondaire)

6. Maintenant que vous l'avez personnalisé, n'est-ce pas simplement ce que j'ai dit?

Non! Le chargeur de classe est déjà restreint

7. L'exemple de relation parent-enfant du chargeur de classe n'est pas un héritage mais une composition

En regardant le code ci-dessous, les lecteurs peuvent réessayer et essayer soigneusement cette phrase: Le chargeur de classe qui charge le chargeur de classe n'est pas le chargeur de classe parent du chargeur de classe

System.out.println(ParentDemo.class.getClassLoader());
System.out.println(ParentDemo.class.getClassLoader().getClass().getClassLoader());
System.out.println(ParentDemo.class.getClassLoader().getParent());
System.out.println(ParentDemo.class.getClassLoader().getParent().getParent());

输出结果:
sun.misc.Launcher$AppClassLoader@18b4aac2
null
sun.misc.Launcher$ExtClassLoader@6e0be858
null

8. La portée de chaque chargeur de classe

Vous pouvez consulter le code source de sun.misc.Launcher

  • BootstrapClassLoader: sun.boot.class.path
  • ExtensionClassLoader: java.ext.dirs
  • AppClassLoader: java.class.path
 public static void main(String[] args) {
     System.out.println("---------BOOT-----------------------");
     String boot = System.getProperty("sun.boot.class.path");
     Arrays.stream(boot.split(";")).forEach(s-> System.out.println(s));
     System.out.println("--------------Ext-------------------");
     String ext = System.getProperty("java.ext.dirs");
     Arrays.stream(ext.split(";")).forEach(s-> System.out.println(s));
     System.out.println("----------APP-----------------------");
     String app = System.getProperty("java.class.path");
     Arrays.stream(app.split(";")).forEach(s-> System.out.println(s));
}

输出结果:
---------BOOT-----------------------
C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\sunrsasign.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar
C:\Program Files\Java\jdk1.8.0_144\jre\classes
--------------Ext-------------------
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext
C:\WINDOWS\Sun\Java\lib\ext
----------APP-----------------------
C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar
C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar
E:\workspace_idea\blogmaven\target\classes 
// 读者注意看这一个  这个是当前项目class文件地址

9. Chargeur de classe personnalisé

  1. Définissez d'abord une classe java chargée Test.java

    public class Test {
       public void say(){
           System.out.println("成功喽!");
       }
    }
  2. Compilez Test.java dans le répertoire spécifié

    javac  -encoding utf-8  -d E:/classes  Test.java 
  3. Hériter de ClassLoader, remplacer la méthode de modèle findClass, appeler defineClass

    /**
    * @author 木子的昼夜
    */
    public class MyClassLoader extends ClassLoader  {
       @Override
       protected Class<?> findClass(String name) throws ClassNotFoundException {
           FileInputStream inputStream = null;
           ByteArrayOutputStream out = null;
           try {
               // 类名  aa.xx 转换为 aa/xx.class
               File file = new File("E:\\classes\\",name.replaceAll("\\.","/").concat(".class"));
               // 获取输入流
                inputStream = new FileInputStream(file);
               // 输出字节流
                out = new ByteArrayOutputStream();
    
               // 转换为字节数组
               int available = inputStream.available();
               byte[] byteArr = new byte[available];
               inputStream.read(byteArr);
    
            // 生成class 
               return defineClass(name,byteArr,0,byteArr.length);
           }catch (Exception e) {
               throw  new ClassNotFoundException();
           }finally {
               // 关闭流
               if (inputStream != null) {
                   try {
                       inputStream.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
               if (out != null) {
                   try {
                       out.close();
                   } catch (IOException e) {
                       e.printStackTrace();
    
                   }
               }
           }
       }
    }
  4. test

    public static void main(String[] args) {
           try {
               Class<?> clazz = new MyClassLoader().loadClass("Test");
               // 获取声明的方法
               Method say = clazz.getDeclaredMethod("say");
               // 创建实例
               Object instance = clazz.newInstance();
               // 调用方法
               say.invoke(instance);
           }catch (Exception e) {
               e.printStackTrace();
           }
    }
    输出结果:
       成功喽!
  5. Le chargeur de classe personnalisé charge les classes auto-chiffrées

    1. Le fichier est le vôtre, vous pouvez le crypter par un algorithme une fois la compilation terminée,
      et lorsque vous le chargez avec un ClassLoader personnalisé, vous pouvez le décrypter vous-même
    2. Peut empêcher la décompilation
    3. Peut empêcher la falsification

10. Compilation hybride

  1. Interprète: interprète bytecode

  2. JIT: Just In - Time compilateur

        1.  -Xmixed 默认为混合模式 
      开始使用解释执行 启动速度快
      对热点代码进行实时检测和编译
        2.  -Xint 使用解释模式 启动快 执行慢
        3.  -Xcomp 使用纯编译模式 启动慢 运行快 
  3. Mode mixte

    1. Interprète + compilation de code à chaud

    2. Interprète

    3. La détection de code à chaud détecte l'utilisation de la compilation de code à chaud

      1.  多次被调用的方法(方法计数器:监测方法执行频率)
          2.  多次被调用的循环(循环计数器:监测循环执行频率)

À suivre...

Il y a beaucoup de photos dans cet article. Si vous n'êtes pas sûr, vous pouvez faire attention au compte public: Muzi's Day and Night

Envoyez "Class Load" pour obtenir l'adresse d'accès de l'image HD

Envoyez "route" pour obtenir le plan de cette série d'articles

Vous pouvez également m'envoyer les questions que vous souhaitez poser, je vous répondrai dès que je le verrai

Enfin, j'ai joint mon compte public et j'ai juste commencé à rédiger un souhait et à progresser ensemble:

Parler de la première partie du processus de chargement de classe

Remarque : Le texte ci-dessus ne représente que des opinions personnelles et est pour référence uniquement. Si vous avez des questions, veuillez le signaler et sortir immédiatement du lit et apporter des corrections.

Je suppose que tu aimes

Origine blog.51cto.com/12198094/2655976
conseillé
Classement