Loading and initialization like jvm

3, Class loading and initialization

Interview questions:

  1. Describe the hierarchy of class loaders?

  2. Parental delegation

  3. Why parent delegation

How is the Class file loaded into memory and executed

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-8VDRdKSX-1641746615741)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image002-164174456853445.jpg)]

3.1 Class Cycle

Class file is in our hard disk, so how to load it into memory requires a total of three major steps

  1. Loading step

Loading is to load the binary contents of the local classfile into memory

  1. Linking steps

    1. Verification verification

    The main process of Verification is to verify that if the byte terminal of the file to be loaded is not CAFEBABE, the process will be rejected.

    1. Preparation

      The main function of the Preparation process is to assign the static variable to the default value, assuming that the definition of public static int i=8; In this process, the value of I is not assigned to 8, but the default value of static variable I is assigned, that is, 0;

    2. Resolution

      This process converts some symbolic references used by the constant pool in the class file to memory addresses

  2. Initializing steps

The static code block will be called only when the static variable is assigned as the initial value in this step.

3.2 ClassLoader

The JVM itself has a class loader level, which is an ordinary class. The loader level is used to load different classes

[external chain image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-vvr29nkh-1641746615741)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image004-164174456853446.jpg)]

[external chain image transfer failed, and the source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-VcsKFrqU-1641746615742)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image006-164174456853547.jpg)]

Note: any classfile loaded into memory will have two parts,

The first partial binary classfile is indeed load ed into memory

The second part generates the class class object. There will be other objects in the class, which refer to the class object, and the class object points to the memory loading of the classfile

Where is the extension stored as a Class object?

Class objects are stored in metaspace

Metaspace is jdk1 In version 8, the Metaspace is the method area. In version 1.8, the permanent generation is removed from the method area. Originally, before version 1.8, part of the PermGenerationspace was changed to the method area, and these two places refer to the method area.

How do you know which classes are loaded by which loaders?

topmost

BootstrapClassLoader

Load lib/rt.jar charset.jar Jar and other core classes are implemented in C + +.

It is mainly responsible for loading the core jars in the jdk, such as runtime Jar or what we usually call string class,Object. Class is located in lib/rt.jar

The top-level loader will be called with null value. There is no such object in the java class to deal with it.

The second floor

ExtClassLoader

Load the extended jar package, JRE / lib / ext / * jar

Or by - DJava Ext.dirs specifies

Third floor

AppClassLoader

Load the contents specified by classpath

Fourth floor

Custom loader

Load the contents of the custom class.

 public class ClassLoaderTest01 {  
     public static void main(String[] args){       
         System.out.println(String.class.getClassLoader());     System.out.println(sun.awt.HKSCS.class.getClassLoader());     System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader());     System.out.println(ClassLoaderTest01.class.getClassLoader());     System.out.println(sun.net.spi.nameservice.dns.DNSNameService.class.getClassLoader().getClass().getClassLoader());     System.out.println(ClassLoaderTest01.class.getClassLoader().getClass().getClassLoader());       } }

The loading process of class loader is called parent delegation.

There is a concept called parent loader in parent delegation. The parent loader here is not an inheritance relationship

[external chain picture transfer failed, and the source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-un024O8k-1641746615744)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image008.gif)]

This figure describes a syntactic inheritance relationship, which has nothing to do with the parent loader.

The parent loader actually refers to a variable in the Classloader source code. This variable is called Classloader and the type name is parent

3.3 parental delegation

The Class file is loaded through a user-defined classloader. If it is not loaded, it delegates its parent loader, appclassloader, to determine whether it is loaded locally. If so, it is loaded directly. If not, it continues to delegate upward until the top-level loader bootstrappclassloader. However, the top-level loader is not loaded, It will delegate downward. When all child loaders are not loaded, an exception classNotFound will be thrown. If the child loader can load, it will be loaded by the child loader.

Parents: it refers to a process from son to father and a process from father to son

Delegate: delegate what you don't want to do to others

When delegating upward, the parent loader always looks in the Cache

This cache can be understood as a list or an array.

Why use parental delegation for interview questions?

\1. Prevent loading the same class file to ensure data security

\2. Ensure that the core class file is not tampered with. Even if it is tampered with, it will not be loaded. Even if it is loaded, it will not be the same class object. In order to ensure the security of class execution.

This part of the code is written dead.

3.4 parent loader

The parent loader is not the loader of the loader, nor is it the loader of the parent class of the loader

The parent loader actually refers to a variable in the Classloader source code. This variable is called Classloader and the type name is parent

   public class ClassLoaderTest02 {  
       public static void main(String[] args){       System.out.println(ClassLoaderTest02.class.getClassLoader());     System.out.println(ClassLoaderTest02.class.getClassLoader().getClass().getClassLoader());     System.out.println(ClassLoaderTest02.class.getClassLoader().getParent());     System.out.println(ClassLoaderTest02.class.getClassLoader().getParent().getParent());     *//System.out.println(ClassLoaderTest02.class.getClassLoader().getParent().getParent().getParent()); *   } }

Class 3.5 loader range

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-tzS4tOlI-1641746615745)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image010-164174456853548.jpg)]

From the execution results of the previous case, we can see that both appclassloader and extclassloader are internal classes of the launcher. Launcher is the wrapper class and startup class of classloader

In the Launcher source code

private static String bootClassPath = System.getProperty("sun.boot.class.path");
final String var1 = System.getProperty("java.class.path");
String var0 = System.getProperty("java.ext.dirs");

sun.boot.class.path is the loading path of bootstrap classloader

java.class.path is the loading path of AppClassloader

java.ext.dirs is the loading path of ExtClassLoader

package com.openlab;    import sun.misc.Launcher;    public class ClassLoaderTest03 {     public static void main(String[] args){      String pathBoot = System.*getProperty*("sun.boot.class.path");    System.*out*.println(pathBoot.replaceAll(";",System.*lineSeparator*()));      System.*out*.println("---------------------------------");    String pathExt = System.*getProperty*("java.ext.dirs");    System.*out*.println(pathExt.replaceAll(";",System.*lineSeparator*()));      System.*out*.println("---------------------------------");    String pathApp = System.*getProperty*("java.class.path");    System.*out*.println(pathApp.replaceAll(";",System.*lineSeparator*()));     } }

3.6 custom loader

Small demo

package com.openlab;    public class ClassLoaderTest04 {   public static void main(String[] args) throws ClassNotFoundException {     Class clazz = ClassLoaderTest04.class.getClassLoader().loadClass("com.openlab.Person");     System.*out*.println(clazz.getName());  *//** class loader can also be used to load resources / / classloadertest04 class. getClassLoader(). getResourceAsStream();    *   } }

Tomcat loaded Servlet

Loading ApplicationContext in Spring framework

For example, when writing some class libraries or modifying the underlying framework. You can load who you want to load.

protected Class<?> loadClass(String name, boolean resolve)   throws ClassNotFoundException  {``// Lock synchronized (getclassloadinglock (name)) {* / / first, check if the class has already been loaded * class <? > C = findloadedclass (name); if (C = = null) {long t0 = system. * nanotime * (); try {` ` / / continue to call the loadClass method recursively using the classloader of the parent if (parent! = null) {C = parent.loadClass (name, false);         }  else {           c = findBootstrapClassOrNull(name);         }       }  Catch (classnotfoundexception E) {* / / classnotfoundexception throw if class not found / / from the non null parent class loader *} ` ` / / call findclass method to find class 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;   } }

\1. Inherit ClassLoader

\2. Rewrite the template method findClass

---- call the defineClass method

Read the class file from the directory and load the class file through the custom loader

Utilizing IO streams

The Java language is relatively easy to decompile

-Prevent Decompilation

-Tamper proof

class files can be encrypted and decrypted

Operation: 1 Implementation of custom loader video to group

2. The content parsed by the classfile needs to be sorted in the form of blog and Xmind

3. Preview the basic knowledge points of JVM

package com.openlab;    import java.io.*;    public class MacluClassLoader extends ClassLoader{     @Override   protected Class<?> findClass(String name) throws ClassNotFoundException {       File file = new File(         "c:/test",         name.replaceAll(".","/").concat(".class"));       try {       FileInputStream fis = new FileInputStream(file);       ByteArrayOutputStream baos = new ByteArrayOutputStream();       int b = 0;       while ((b = fis.read())!=0){         baos.write(b);       }        byte[] bytes = baos.toByteArray();         baos.close();       fis.close();         return defineClass(name,bytes,0,bytes.length);       } catch (FileNotFoundException e) {       e.printStackTrace();     } catch (IOException e) {       e.printStackTrace();     }       return super.findClass(name);*// throw ClassNotFoundException *   }     public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {       ClassLoader cl = new MacluClassLoader();     Class clazz = cl.loadClass("com.openlab.Person");       Person person = (Person) clazz.newInstance();     person.m();       System.*out*.println(cl.getClass().getClassLoader());     System.*out*.println(cl.getParent());     }   }

We can define our own format classloader. Generally, the class file is a binary file stream. We can encrypt and decrypt the class file in a relatively simple way

Encryption: a number can be defined through ^ XOR. During the write operation after reading each byte, the data obtained in the stream and the number can be used for XOR algorithm, so the encryption operation can be carried out

Decryption: the byte number completes the decryption operation.

package com.openlab;    import java.io.*;    public class MacluClassLoaderWithEncription extends ClassLoader{     public static int *seed* = 0B10110110; *//** carry out digital encryption algorithm * @ override protected class <? > findClass(String name) throws ClassNotFoundException {       File file = new File(         "c:/test",         name.replaceAll(".", "/"). concat(".class"));        try {       FileInputStream fis = new FileInputStream(file);       ByteArrayOutputStream baos = new ByteArrayOutputStream();       int b = 0;       while ((b = fis.read())!=0){         baos.write(b^*seed*);       }          byte[] bytes = baos. toByteArray();          baos. close();        fis. close();          return defineClass(name,bytes,0,bytes.length);       }  catch (FileNotFoundException e) {       e.printStackTrace();     }  catch (IOException e) {       e.printStackTrace();     }        return super. findClass(name);*//  throw ClassNotFoundException *   }     public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException,  IOException {       *encFile*("com.openlab.Person");     ClassLoader cl = new MacluClassLoaderWithEncription();       Class clazz = cl.loadClass("com.openlab.Person");       Person person = (Person) clazz.newInstance();     person.m();       System.*out*.println(cl.getClass().getClassLoader());     System.*out*.println(cl.getParent());     }      private static void encFile(String name) throws IOException {     File file = new File(         "c:/test/",         name.replace(".", "/"). concat(".class"));        FileInputStream fis = new FileInputStream(file);      FileOutputStream fos = new FileOutputStream(         new File("c:/test",name.replaceAll(".", "/"). concat(".macluclass")));      int b = 0;        while ((b = fis.read())!=- 1){       fos.write(b^*seed*);     }      fis. close();      fos. close();   } }

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-d3Qyd8J2-1641746615745)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image012-164174456853549.jpg)]

Generate encrypted files

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-jbhic0r9-1641746615746) (C: / users / HX / desktop / Xuexi /% E6% 94% be% E5% 9b% be / clip_image014-1641744568535550. JPG)]

Verify that the encrypted file is garbled after opening.

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-C9vkEySu-1641746615746)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image016-164174456853551.jpg)]

3.7 editor

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-7ZRO5OWR-1641746615747)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image018-164174456853552.jpg)]

Interpreter: bytecode interpreter

Just In Time compiler

Is the Java language an interpreted language or a compiled language

If you want an interpreter, you can use the interpreter. If you want to compile, you can also use the compiler to see how the requirements are written. You can set them through some parameters of the JVM.

The default is a mixed mode

Mixed mode: using interpreter + hotspot editor hotspot

The initial stage is executed by interpretation

The detection default value of hotspot code is 10000

Method called multiple times (method counter: detects the execution frequency of the method)

Loop called multiple times (loop counter: detect the execution frequency of the loop)

When such a loop, a method or a piece of code will always be called many times, that is, when the execution frequency of this code is particularly high, simply compile this code into local code, and directly access the local code the next time. There is no need for the interpreter to interpret and execute it. So as to improve efficiency. This way of executing code is called mixed mode.

So why not compile it directly into local code to make it execute faster? Can you improve efficiency?

  1. The execution efficiency of the current interpreter is very high. In some simple code execution, it does not belong to the compiler.

  2. If the program to be executed depends on a large number of class libraries, the startup process will be very slow if it is compiled in the virtual machine.

-Xmixed is mixed mode:

Start interpretation and execution, start faster, detect and compile hot code.

-Xint interpretation mode

Fast startup and slow execution

-Xcomp pure compilation mode,

Slow startup and fast execution

Test these three jvm parameters

  public class WayToRunTest01 {     public static void main(String[] args){ 
        *//**This code has been executed many times in a short time. Please ask the JVM virtual machine to optimize it*     
      for (int i = 0;i<10_0000;i++)       *m*();    
       long start =System.*currentTimeMillis*(); 
           for (int i = 0;i<10_0000;i++){       *m*();     }       
           long end = System.*currentTimeMillis*();     S
           ystem.*out*.println(end-start);     
           }     
           *//** the method itself is meaningless and time-consuming* 
             public static void m(){ 
                   for (int i = 0;i<10_0000L;i++){      
                    long j = i%3;     }     } }

Default blend mode

[external chain image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-foluxqps-1641746615748) (C: / users / HX / desktop / Xuexi /% E6% 94% be% E5% 9b% be / clip_image020-1641744568535553. JPG)]

In the JVM's execution parameters, - Xint interprets the schema

Go back to wash and sleep very slowly

[the external chain image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (IMG ltdknqvi-1641746615749) (C: / users / HX / desktop / Xuexi /% E6% 94% be% E5% 9b% be / clip_image022-164174456853554. JPG)]

Compiled only mode - Xcomp

[external chain picture transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-Y7Nc4xFC-1641746615749)(C:/Users/HX/Desktop/xuexi/%E6%94%BE%E5%9B%BE/clip_image024-164174456853555.jpg)]

[external link image transfer failed. The source station may have anti-theft chain mechanism. It is recommended to save the image and upload it directly (IMG dxaqtnko-1641746615749) (C: / users / HX / desktop / Xuexi /% E6% 94% be% E5% 9b% be / clip_image026-164174456853556. JPG)]

3.8 lazy loading

Strictly speaking, it should be called lazyInitializing

The JVM specification does not specify when to load

Strictly specifies the initialization rule extension

\1. When the new object getstatic accesses a static variable and putstatic accesses a static instance, the invokestatic instruction

The above instructions must initialize this class, except for accessing the final variable.

\2. When reflection calls

\3. When initializing a subclass, first initialize the parent class

\4. The main class to be executed when the virtual machine is started must be initialized

\5. Dynamic language supports Java lang.invoke. When the methodhandler parses the method handle whose result is ref getstatic ref putstatic ref invokestatic, this class must be initialized.

This case mainly depends on when to print P and X

package com.openlab;    public class LazyLoadingTest {     public static void main(String[] args) throws ClassNotFoundException {  *//    P p;  //     X x = new X();  //     System. out. println(P.i);  //     System. out. println(P.j); *      Class.* forName*("com.openlab.LazyLoadingTest$P");       }      Public static class P {final static int * I * = 8; * / / * * the value of print final is * static int * J * = 9; static {system. * out *. Println ("P");}} public static class X extends P{     static{       System.*out*.println("X");     }   } }

Interview questions:

How to break the parent delegation mode of classloader?

By overriding the loadClass method in Classloader instead of the findClass method, the mechanism of parental delegation can be broken.

When to break the parental delegation mechanism:

  1. At jdk1 If you want to customize the classloader before version 2, you must override the loadClass method

  2. The loader object ThreadContextClassLoader that sets its own thread context in a thread can realize the code of the basic call implementation class through thread SetContextClassLoader.

  3. Modular hot deployment and hot start

Both osgi and tomcat have their own modules to specify classloader s, which can load different versions of objects in the same class library. At present, this method is used more.

There can be multiple web application objects in Tomcat. Two web applications are loaded, but their versions are different. In this case, the parental delegation can be broken.

Note: the class names are the same, but the versions are different. If the parental delegation mechanism is adopted, the two objects cannot be loaded into the same space, because during the loading process, if a class with the same name is found in the same space, it will not be loaded.

So every web application of tomcat has a classloader

Parental delegation mode loading

package com.openlab;    public class ClassReloadingTest {     public static void main(String [] args) throws ClassNotFoundException {       MacluClassLoader classloader = new MacluClassLoader();       Class clazz = classloader.loadClass("com.openlab.Person");       classloader = null;     System.*out*.println(clazz.hashCode());     classloader = null;       classloader = new MacluClassLoader();     Class clazz1 = classloader.loadClass("com.openlab.Person");     System.*out*.println(clazz1.hashCode());       System.*out*.println(clazz == clazz1);       } }

As can be seen from the above case, even if the classloader object is re created for parent delegation, the object that was once loaded will still be loaded when it is loaded again.

How should hot deployment be implemented

import java.io.*;
public class T012_ClassReloading2 {
    private static class MyLoader extends ClassLoader {
        @Override     public Class<?> loadClass(String name) throws ClassNotFoundException {
            File f = new File("C:/test/" + name.replace(".", "/").concat(".class")); 
            if(!f.exists()) return      super.loadClass(name);      
            try {      
                InputStream is = new FileInputStream(f);   
                 byte[] b = new byte[is.available()];         is.read(b);     
                return defineClass(name, b, 0, b.length);       
            } catch ( FileNotFoundException e) {         e.printStackTrace();       
                                               } catch (IOException e) {    
                e.printStackTrace();      
            }       return super.loadClass(name);    
        }   
    }     
    public static void main(String[] args) throws Exception {   
        MyLoader m = new MyLoader(); 
        Class clazz = m.loadClass("com.openlab.Person");   
        m = new MyLoader(); 
        Class clazzNew = m.loadClass("com.openlab.Person");     
        System.out.println(clazz == clazzNew);   } }

Last jvm foundation to entry class file structure
The next one is not available yet

Keywords: Java jvm Back-end

Added by arbab on Sun, 09 Jan 2022 18:57:26 +0200