JVM learning: classloader

Keywords: Java jvm

What is a classloader:

public class ClassInit {
    public static void main(String[] args) {
        ClassLoader c=ClassInit.class.getClassLoader();
    }
}

The ClassLoader above is the ClassLoader

Print c, and notice a Launcher class:

sun.misc.Launcher$AppClassLoader@18b4aac2

 

Enter the Launcher class and notice two pieces of code:

var1 = Launcher.ExtClassLoader.getExtClassLoader();
this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);

What is the relationship between ExtClassLoader and AppClassLoader?

 

Modify to the following code:

public class ClassInit {
    public static void main(String[] args) {
        ClassLoader c = ClassInit.class.getClassLoader();
        while (c != null) {
            System.out.println(c);
            c = c.getParent();
        }
    }
}

Print:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@1540e19d

So we come to the conclusion: AppClassLoader has a father who is ExtClassLoader

 

Continue to analyze ClassLoader, and notice a piece of code:

    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)

Exclusive lock ensures that only one class can be loaded at the same time

Then check whether the class has been loaded and return directly if it has been loaded;

If it has not been loaded, it will load its father recursively until there is no father, and finally execute findBootstrapClassOrNull()

 

Looking down, I find this Code:

    // return null if not found
    private native Class<?> findBootstrapClass(String name);

This function has no function body and is modified by native, which means calling a local method

The local method is called here, and the local method interface is different according to the operating system, and then the local method library is called.

 

come to conclusion:

The loading order of a class is: bootstrappclassloader --- > extclassloader --- > appclassloader

The checking order of a class is: appclassloader --- > extclassloader --- > bootstrappclassloader

 

Why does the loading order start with bootstrappclassloader?

Write a new code. The package name and class name are the same as the java source List:

package java.util;

public class List{
 public static void main(String[] args){
   xxxxxx
 }
}

Discovery failed to run, error reported: main method not found in class java.util.List

It's very reasonable that it can't run, otherwise a hacker can easily embed virus code, and then add it to the JVM through a custom classloader

 

This mechanism is called: parental appointment

Purpose: Safety

1. If the parent class can be loaded, the child class is not allowed to load

2. Ensure that a class is loaded only once

 

To judge whether two objects are equal, the most important condition is to see whether they are a classloader:

Write a code:

package org.dreamtech.cl;

import java.io.IOException;
import java.io.InputStream;

public class ClassInit {
    //Custom class loader
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        ClassLoader loader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                try {
                    String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
                    InputStream is = getClass().getResourceAsStream(fileName);
                    if (is == null) {
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b, 0, b.length);
                } catch (IOException e) {
                    throw new ClassNotFoundException();
                }
            }
        };
        String className = "org.dreamtech.cl.ClassInit";
        Object o1 = ClassInit.class.getClassLoader().loadClass(className).newInstance();
        Object o2 = loader.loadClass(className).newInstance();
        System.out.println(o1 == o2);
        System.out.println(o1.equals(o2));
        System.out.println(o1 instanceof org.dreamtech.cl.ClassInit);
        System.out.println(o2 instanceof org.dreamtech.cl.ClassInit);
        System.out.println(o1.getClass().getClassLoader());
        System.out.println(o2.getClass().getClassLoader());
    }
}

Print as follows:

false
false
true
false
sun.misc.Launcher$AppClassLoader@18b4aac2
org.dreamtech.cl.ClassInit$1@14ae5a5

Posted by bluedot on Thu, 12 Mar 2020 04:54:12 -0700