[Deep and shallow-JVM] (76): classloader

Posted by ungovernable on Mon, 16 Sep 2019 13:24:26 +0200

Method

  • public Class<?> loadClass(String name) throws ClassNotFoundException

Play Class instances of this class by class name

  • protected final Class<?> defineClass(byte[] b,int off,int len)

According to the given bytecode stream b, off and len parameters represent the position and length of the actual class information in the byte array, where byte array B is retrieved externally by classloader

  • protected Class<?> findClass(String name)throws ClassNotFoundException

View a class

  • protected final Class<?> findLoadedClass(String name)

classification

  • BootStrap ClassLoader
  • Extension ClassLoader
  • AppClassLoader


The startup class loader is responsible for loading the core class of the system (rt.jar's java class), expanding the class loader to load the class in% JAVA_HOME/lib/ext/*.jar, applying the class loader to load the user class (classpath), and customizing the class loader to load some classes with special paths (customized classloader)

Parental commitment

  1. The current classloader first queries whether this class has been loaded from its own loaded classes, and if it has already been loaded, returns directly to the original loaded classes.
  2. When the loaded class is not found in the current classloader's cache, the parent class loader is delegated to load. The parent class loader uses the same strategy. First, it checks its own cache, and then delegates the parent class to load until bootstrap classloader.
  3. When all parent loaders are not loaded, they are loaded by the current class loader and put into their own cache. They are returned directly on the next request.
  4. Continuous cyclic repetition

Effect

  • Unification of basic classes for each class loader

Jar-cvf test.jar HelloLoader.class packages classes into jars

Extension ClassLoader

Example: Place a self-jar package in the ext path and load it

package com.mousycoder.server;

public class HelloWorld {

    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

idea generates helloworld.jar by structs - > artifacts - > jar and then build - > build artifacts - > build
Put it in / Library / Java / Java VirtualMachines / jdk1.8.0. JDK / Contents / Home / JRE / lib / ext

package com.mousycoder.mycode.thinking_in_jvm;

import java.lang.reflect.Method;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-06 10:35
 */
public class ExtClassLoader {

    public static void main(String[] args) throws ClassNotFoundException {
        System.out.println(System.getProperty("java.ext.dirs"));
        Class<?> helloClass = Class.forName("com.mousycoder.server.HelloWorld");
        System.out.println(helloClass.getClassLoader());
    }
}

output

/Users/mousycoder/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
sun.misc.Launcher$ExtClassLoader@610455d6

You can see that the ExtClassLoader loads the java.ext.dirs directory

Custom Class Loader

package com.mousycoder.mycode.thinking_in_jvm;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-06 11:13
 */
public class MyClassLoader extends ClassLoader {

    private final static Path DEFAULT_CLASS_PATH = Paths.get("","/Users/mousycoder/My");

    private final Path classDir;

    public MyClassLoader(){
        super();
        this.classDir = DEFAULT_CLASS_PATH;

    }

    public MyClassLoader(String classDir){
        super();
        this.classDir = Paths.get(classDir);
    }

    public MyClassLoader(String classDir, ClassLoader parent){
        super(parent);
        this.classDir = Paths.get(classDir);
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            byte[] classBytes = this.readClassBytes(name);

            if (null == classBytes || 0 == classBytes.length){
                throw new ClassNotFoundException("can not load the class" + name);
            }
            return this.defineClass(name,classBytes,0,classBytes.length);
        } catch (IOException e){
            e.printStackTrace();
        }
        return null;
    }


    private byte[] readClassBytes(String name) throws ClassNotFoundException, IOException {
        String classPath = name.replace(".","/");
        Path classFullPath = classDir.resolve( "HelloWorld1.class");
        if (!classFullPath.toFile().exists()){
            throw new ClassNotFoundException("The class" + name + "mpt found");
        }

        try (ByteArrayOutputStream baos = new ByteArrayOutputStream()){
            Files.copy(classFullPath,baos);
            return baos.toByteArray();
        } catch (IOException e){
            throw new ClassNotFoundException("load the class " + name + "occur error",e);
        }

    }


    @Override
    public String toString() {
        return "My ClassLoader";
    }
}

package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-06 11:34
 */
public class MyClassLoaderTest {

    public static void main(String[] args) throws ClassNotFoundException {
        MyClassLoader classLoader = new MyClassLoader();
        Class<?> class1 = classLoader.loadClass("com.mousycoder.mycode.thinking_in_jvm.HelloWorld1");
        System.out.println(class1.getClassLoader());
    }
}
package com.mousycoder.mycode.thinking_in_jvm;

/**
 * @version 1.0
 * @author: mousycoder
 * @date: 2019-09-06 11:46
 */
public class HelloWorld1 {
    public static void main(String[] args) {
        System.out.println("Hello world1 ");
    }
}

Change helloword1 into class and put it in / Users/mousycoder/My directory
Output My ClassLoader loads the class on behalf of a custom class loader

context class loader

Effect

Break the parental delegation mechanism, so that the upper parent class loader can use the loader of subclasses to load objects, such as the interface class in Spi in the system loader, but the implementation class in the application loader.

Tomcat class loader

objective

  1. Ensure that each application's libraries are isolated independently (even if they are different versions of the same qualified name)
  2. Guarantee the sharing of the same class library and the same version of the class library
  3. Guarantee the class library and program independence of container itself

Loading order

  1. bootstrap boot class loader
  2. system System Class Loader
  3. Application class loader WEB-INF/classes
  4. Application Class Loader WEB-INF/lib
  5. common class loader CATALINA/lib

Topics: Java JDK network Tomcat