Java learning notes 18 class loading mechanism

Class life cycle
  1. Loading: reading binary content
  2. Verification: verify class file format specification, semantic analysis, reference verification, bytecode verification
  3. Preparation: allocate memory, set initial value of variable decorated by static class
  4. Parsing: class, interface, field, class method, etc
  5. Initialization: assigning values to static variables; executing static code blocks
  6. Using: to create an instance object
  7. Uninstallation: uninstalling from the JVM method area
Class loader

Class loader is responsible for loading classes, searching for class resources in specified locations such as network, jar, zip, folder, binary data, memory, etc.

A java program runs with at least three class loader instances, which are responsible for loading different classes.

  1. Bootstrap loader core class library loader: C/C + + implementation, no corresponding java class: null; load JRE_HOME/jre/lib directory, or user configured directory; JDK core class library rt.jar String...
  2. Extension Class loader: an instance of ExtClassLoader: load JRE? Home / JRE / lib / ext directory, JDK expansion package, or user configured directory
  3. application class loader user application loader: AppClassLoader instance: load the directory specified by java.class.path, user application class path or Java command runtime parameter - cp
Verification problem
  1. View the loader corresponding to the class

    View through JDK API: java.lang.getClassLoader()

    Returns the classloader of the loaded class

    If the class is loaded by bootstrappclassloader, this method will return null in this implementation.

  2. How does the JVM know where our classes are

    class information is stored in different places, such as desktop jar, project bin directory, target directory, etc

    View the openjdk source code: sun.misc.Launcher.AppClassLoader

    Conclusion: read the java.class.path configuration and specify which address to load the class resource

    Verification process: using jps and jcmd commands

    • jps viewing native JAVA process
    • View runtime configuration: jcmd process No. vm.system ﹣ properties
  3. Class does not load repeatedly

    Class uniqueness: the same class loader and class name represent the same class.

    Identification method: ClassLoader Instance id + PackageName + ClassName

    Verification method: use class loader to load different versions of the same class multiple times, and check whether the latest code will be loaded.

  4. Class uninstall

    When will classes be uninstalled? The following two conditions are met:

    • All instances of this Class have been GC;
    • The ClassLoader instance to load this class has been GC;

    Verification method: add - verbose:class parameter in jvm startup, and output the log information of class loading and unloading

  5. Parents Delegation Model

    In order to avoid repeated loading, level by level delegation from bottom to top and level by level search from top to bottom.

    First, I will not try to load the class myself, but delegate the request to the parent loader to complete it;

    This is the case at each level of the loader, so all classloader requests are passed to the upper level boot classloader.

    Only when the parent loader feedback that it cannot complete the load request (no corresponding class is found in the search scope of the loader), the child loader will try to load by itself.

    Note: there is no parent-child relationship between class loaders. "Parents" is a translation, which can be understood as a logically defined parent-child relationship.

Test code

import java.net.URL;
import java.net.URLClassLoader;
import java.util.concurrent.TimeUnit;

public class ClassLoaderDemo {
    public static void main(String[] args) throws Exception {
        // View the loader instance of the class
        classLoaderView();
        // Hot load, specify class to load
        classLoaderTest();
    }

    /**
     * View the loader instance of the class
     *
     * @throws Exception
     */
    public static void classLoaderView() throws Exception {
        // Load the BootStrap ClassLoader of the core class library
        System.out.println("Core class library loader:" + ClassLoaderDemo.class.getClassLoader()
                .loadClass("java.lang.String").getClassLoader());
        // Loading Extension ClassLoader of extension library
        System.out.println("Expand class library loader:" + ClassLoaderDemo.class.getClassLoader()
                .loadClass("com.sun.nio.zipfs.ZipCoder").getClassLoader());
        // Load application's
        System.out.println("Application library loader:" + ClassLoaderDemo.class.getClassLoader());
        // Parents Delegation Model
        System.out.println("Parent class of application library loader:" + ClassLoaderDemo.class.getClassLoader()
                .getParent());
        System.out.println("The parent of the application library loader's parent class:" + ClassLoaderDemo.class.getClassLoader()
                .getParent().getParent());
    }

    /**
     * Hot load, specify class to load
     *
     * @throws Exception
     */
    public static void classLoaderTest() throws Exception {
        // jvm classes in place
        URL classUrl = new URL("file:D:\\");
        // 2. Uninstall the test class
        //URLClassLoader loader = new URLClassLoader(new URL[]{classUrl});
        // 3. Test the parent delegation mechanism
        // If this loader is used as the parent loader, the following hot update will fail. Because of the parent delegation mechanism, HelloService is actually loaded by this class loader;
        //URLClassLoader parentLoader = new URLClassLoader(new URL[]{classUrl});
        while (true) {
            // 2. Uninstall the test class
            //if (loader == null) {
            //    break;
            //}
            // 3. Test the parent delegation mechanism
            // Create a new classloader whose parent loader is parentLoader above
            //URLClassLoader loader = new URLClassLoader(new URL[]{classUrl}, parentLoader);
            // 1. The class will not be loaded repeatedly. Create a new class loader
            URLClassLoader loader = new URLClassLoader(new URL[]{classUrl});

            Class clazz = loader.loadClass("LoaderTestClass");
            System.out.println("LoaderTestClass Class loader used:" + clazz.getClassLoader());

            Object newInstance = clazz.newInstance();
            Object value = clazz.getMethod("test").invoke(newInstance);
            System.out.println("call getValue The return value obtained is:" + value);

            // Once in 3 seconds
            TimeUnit.SECONDS.sleep(3L);
            System.out.println();

            // 2. Uninstall the test class
            // help gc  -verbose:class
            //newInstance = null;
            //loader = null;
        }

        // 2. Uninstall the test class
        //System.gc();
        //TimeUnit.SECONDS.sleep(3L);
    }
}

LoaderTestClass.java

public class LoaderTestClass {
    public static String value = getValue();

    static {
        System.out.println("##########static code");
    }

    private static String getValue() {
        System.out.println("##########static method");
        return "Test";
    }

    public void test() {
        System.out.println("HelloWorld" + value);
    }
}

Tags: Programming Java jvm JDK network

Posted on Tue, 03 Dec 2019 04:17:21 -0500 by cab