Class loading process

Loading:

  1. Defines a binary byte stream of a class by its fully qualified name
  2. Convert the static storage structure represented by this byte stream to the runtime data structure of the method area
  3. Generate a java.lang.Class object in memory that represents the Class and acts as an access point for the Class’s various data in the method area

Validation:

  1. Verify the class byte stream to ensure that the byte stream in the class file contains information in accordance with all constraints of the Java Virtual Machine Specification, and ensure that the information does not endanger the security of the virtual machine after being run as code.

Preparation:

  1. The stage of formally allocating memory and setting initial values for variables defined in a class (i.e. static variables, static modified variables);

Resolution:

  1. The parsing phase is the process by which the Java VIRTUAL machine replaces symbolic references in the constant pool with direct references.

Class loader

Bootstrap Class Loader: a core Class library in the lib directory that loads the JRE, such as rt.jar and charsets.jar

The Extension Class Loader is responsible for loading the JAR Class package in the ext Extension directory in the lib directory of the JRE.

The Application ClassLoader is responsible for loading the class package in the Classpath path. You mainly load your own classes

Custom loader: loads a class package in a custom path.

Example:


public class TestJDKClassLoader {
    public static void main(String[] args) {
        System.out.println(String.class.getClassLoader());
        System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName());
        System.out.println(TestJDKClassLoader.class.getClassLoader().getClass().getName());
        System.out.println();
        ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
        ClassLoader extClassLoader = appClassLoader.getParent();
        ClassLoader bootstrapLoader = extClassLoader.getParent();
        System.out.println("the appClassLoader:"+appClassLoader);
        System.out.println("the extClassLoader:"+extClassLoader);
        System.out.println("the bootstrapLoader:"+bootstrapLoader);
        System.out.println();
        System.out.println("BootstrapLoader loads the following files:");
        URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
        for (URL urL : urLs) {
            System.out.println(urL);
        }
        System.out.println();
        System.out.println("ExtClassLoader loads the following files:");
        System.out.println(System.getProperty("java.ext.dirs"));
        System.out.println();
        System.out.println("AppClassLoader loads the following files:");
        System.out.println(System.getProperty("java.class.path")); }}Copy the code
null
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$AppClassLoader

the appClassLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
the extClassLoader:sun.misc.Launcher$ExtClassLoader@7ea987ac
the bootstrapLoader:nullBootstrapLoader loads the following files: file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/resources.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/rt.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/sunrsasign.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/jsse.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/jce.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/charsets.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/lib/jfr.jar
file:/C:/Program%20Files/Java/jdk18.. 0 _181/jre/classes extClassLoader loads the following Files: C:\Program Files\Java\jdk18.. 0 _181\jre\lib\ext; C: Windows\Sun\Java\lib\ext appClassLoader loads the following files:.... C: Program Files\Java\jdk18.. 0 _181\jre\lib\rt.jar;
G:\IdeaProjects\java-study\class-loader\target\classes;
D:\Users\hello\AppData\Local\JetBrains\Toolbox\apps\IDEA-U\ch-0\193.691118.\lib\idea_rt.jar
Copy the code
  1. The parent of appClassLoader is extClassLoader; Parent of extClassLoader is null;
  2. Many of the jars loaded by class loaders are repetitive; So how do you avoid reloading?

Parental delegation model

The following is the loadClass method of the ClassLoader. The parent delegate model is implemented by the following code;

protectedClass<? > loadClass(String name,boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) { / / lock
            // First, check if the class has already been loadedClass<? > c = findLoadedClass(name);// Determine if you have already loaded it
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                    if(parent ! =null) { // Call the parent class to load
                        c = parent.loadClass(name, false);
                    } else { // Use BootstrapClassLoader to loadc = findBootstrapClassOrNull(name); }}catch (ClassNotFoundException e) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) { // None of the above is loaded
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name); // Call your own findClass to find; This method is empty, custom loader rewrite;

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

Why design the parental delegation model

  1. Sandbox security mechanism, Java core class library by the specified class loader to load, to prevent the core class library tamper;
  2. Avoid reloading, when the parent loader is already loaded, do not need to load again;

Custom class loaders

As you can see from the flowchart above, there are two main steps to a custom classloader;

  1. This inheritance;
  2. Override the findClass method;

Follow the steps above to customize a class loader:

    ClassLoader classLoader = new ClassLoader() {
        @Override
        protectedClass<? > findClass(String name)throws ClassNotFoundException {
            String path = name.replaceAll("\ \."."/");
            try (FileInputStream is = new FileInputStream("H:/test/" + path + ".class")) {
                byte[] b = new byte[is.available()];
                is.read(b);
                return defineClass(name, b, 0, b.length);
            } catch (IOException e) {
                throw newClassNotFoundException(); }}};Copy the code

This is a simple class loader; Notice the flow of the parent delegate model, where the findClass method is called at the end;

Break the parent delegate model

The superparent delegation model is not a mandatory model, but rather a class loader implementation recommended by Java designers to developers. Most class loaders in the Java world follow this model, but there are exceptions; For details, see In Depth advanced Features and Best Practices of the Java Virtual Machine JVM or a blog on the Web.