What is the heat load - Custom loader

First, what is the thermal load

Simply put, do not restart a project, so that part of the code update, the principle is achieved through java class loader. Due to lack of monitoring makes loading class safety can not be guaranteed, generally used in the development environment and accelerate the development efficiency. Commonly known as the developer mode. To achieve self-defined front loader, first talk about the JVM's class loader.

Two, JVM loader

1、BootStrap ClassLoader

BootStrap ClassLoader class called boot loader, is the top of the parent class loader loads the core class ,, such as java.lang *, java.uti * etc;.. These classes are $ JAVA_HOME / jre / lib / rt .jar;

2、Extension ClassLoader

Extension ClassLoader called extension class loader is responsible for loading the extended package at% JAVA_HOME% / jre / lib / ext / directory

3、Application ClassLoader

Application ClassLoader called application class loader is responsible for loading classes in classpath environment variable

Class loading mechanism

How it works: the use of parent class loader delegate mechanism, in simple terms, first determine whether an application is loaded when it is too loaded, if not then to load, and determine whether the parent, if the parent is required to load, to top then loading the package according to the position of the parent class, subclass does not meet the required load.

Benefits: avoid repeated loading, can guarantee the security of class loading, if himself wrote a String bag, whether it will replace the String class jdk package it? Obviously not, because of the use of this mechanism to avoid this problem.

protected Class<?> loadClass(String name, boolean resolve)
    throws ClassNotFoundException
{
    synchronized (getClassLoadingLock(name)) {
        // 首先判断该类是否已经被加载过
        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) {
                // ClassNotFoundException thrown if class not found
                // from the non-null parent class loader
            }

            if (c == null) {
                //自定义加载,findClass是个空方法就是让我们重写的
                long t1 = System.nanoTime();
                c = findClass(name);

                // this is the defining class loader; record the stats
                sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                sun.misc.PerfCounter.getFindClasses().increment();
            }
        }
        if (resolve) {
            resolveClass(c);
        }
        return c;
    }
}
复制代码

JVM is how to determine whether a class is loaded through it? By findLoadedClass (name), that is java virtual machine has recorded this loader has given the boot loader binary name of a class, the class of the binary name is returned. Otherwise, it returns null.

Third, custom loader

First create a new class and inherit ClassLoader. And rewrite findClass () method. Comment write method has been useful.

public class MyClassLoader extends ClassLoader {
@Override
//通过名称找到具体class文件,并进行加载
protected Class<?> findClass(String name) {
    byte[] b = loadClassData(name);
    name = name.split("\\.")[1];
    //然后通过defineClass()将二进制文件转化为Class对象
    return super.defineClass(name, b, 0, b.length);
}
 //这个方法就是将具体位置的class文件转化为二进制流
private byte[] loadClassData(String name) {
    try {
        name = name.replace(".", "\\");
        FileInputStream fileInputStream = new FileInputStream(new File("D:\\IntelliJ IDEA 2019.1\\JavaHotFix\\" + name+".class"));
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        int i = 0;
        while ((i = fileInputStream.read()) != -1) {
            byteArrayOutputStream.write(i);
        }
        fileInputStream.close();
        return byteArrayOutputStream.toByteArray();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
复制代码

} Easily define an object and a method defined

public class People {
    public void hello() {
        System.out.println("我是People");
    }
}
复制代码

carry out testing

public class Main {
public static void main(String[] args) {
    while (true) {
        try {
            MyClassLoader myClassLoader = new MyClassLoader();
            Class<?> clazz = myClassLoader.loadClass("src.People");
            Object people =  clazz.newInstance();
            clazz.getMethod("hello").invoke(people);
            Thread.sleep(2000);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }  catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

    }
}
}
复制代码

After starting: As the level in this catalog, be the first

After startup, change the People's hello () method will get re-again javac
Project structure:

Small bug: Since the beginning of the direct name written directly People can not lead to repeated thermal load, only to find after the break point, did not use the loader to the original limit called People lead directly classpath was loaded, that is, by the parent AppClassLoader class is loaded.

Thank you, good brother can feel good to play on the public screen.

Guess you like

Origin juejin.im/post/5d161289e51d455070226fe0