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:



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) {
            c = c.getParent();



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){

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() {
            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()];
                    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 instanceof org.dreamtech.cl.ClassInit);
        System.out.println(o2 instanceof org.dreamtech.cl.ClassInit);

Print as follows:


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