当前位置:网站首页>Custom class loader loads network class

Custom class loader loads network class

2022-07-07 07:54:00 cristianoxm

One 、JDK The following three types are provided by default ClassLoader

  • BootStrap ClassLoader: It's called the boot class loader ,C++ Realized , yes Java The top-level classloader in the class loading hierarchy (JVM Initialized after startup ), Responsible for loading JDK Core class library in , Such as :rt.jar、resources.jar、charsets.jar etc. ;
  • ExtensionClassLoader: It's called an extended class loader , Responsible for loading Java The extended class library of , The default load JAVA_HOME/jre/lib/ext/ All of this jar. The loader has java Realized , from Bootstrploader load ExtClassLoader, And will ExtClassLoader The parent loader of is set to Bootstrploader;
  • AppClassLoader: It's called a system class loader , Responsible for loading the application classpath All under directory jar and class file . notes : In addition to the three ,jdk Allow custom class loaders ;

Two 、 Parents delegate

ClassLoader The parent delegation model is used to search for the properties of classes , Every ClassLoader Instance has a reference to the parent loader ( Not an inherited relationship , It's an inclusive relationship ), Virtual machine built-in classloader (BootstrapClassLoader) There is no parent loader in itself , But it can be used for other purposes ClassLoader Instance's parent loader . When One ClassLoader When an instance needs to load a class , It will try to check from the bottom up ( Check the parent loader ) Whether the class has been loaded , If a loader has loaded this class, it will directly return this class object , until bootstrap ClassLoader. Then load the class from top to bottom , First, the top-level class loader BootstrapClassLoader Attempt to load , If it's not loaded into , Then transfer the task to Extension ClassLoader Attempt to load , If it doesn't load into , Is passed on to AppClassLoader Loading , If it doesn't load either , Is returned to the originator of the delegate , From it to the specified file system or network, etc URL Load the class in . If none of them are loaded into this class , Throw out ClassNotFoundException abnormal .

 Insert picture description here

  • Why use a parent delegation model ?

    Because this can avoid repeated loading , When the father has loaded the class , There is no need ClassLoader Load again . Considering the safety factor , Let's think about , If you don't use this delegation mode , Then we can use the customized String To dynamically replace java The core api Type defined in , There will be a very big security risk , And the way parents entrust , This can be avoided , because String Already booted class loader at boot time (BootstrcpClassLoader) load , So user defined ClassLoader Never load a self written String, Unless you change JDK in ClassLoader Default algorithm for search class .

  • JVM In judging two class Is it the same , It's not just about judging whether two class names are the same , And to determine whether it is loaded by the same classloader instance . Only when both are satisfied ,JVM I think these two class It's the same .

3、 ... and 、 Customize classloade

To customize classloader We need to inherit java.lang.ClassLoader class . There are several important methods in this class , but If you want to follow the parental delegation mechanism , You just need to rewrite findClass Method ; If you want to change the parental delegation , Then rewrite loadClass Method .

  • To follow the parental delegation mechanism , And load the network class As an example
// Package name is very important , Custom class loader , You need to specify the full class name 
package com;
public class Hello {
    
    public void say(){
    
        System.out.println("hello");
    }
    public void say1(){
    
        System.out.println("hello1");
    }
    public void say2(){
    
        System.out.println("hello2");
    }
}

Compile the above into .class file , On the remote server . as follows

 Insert picture description here

@Slf4j
public class CustomClassLoader extends ClassLoader{
    
    private final String classUrl;
    public CustomClassLoader(String classUrl) {
    
        super();
        this.classUrl = classUrl;
    }
    /* classLoader It will be loaded in the parent class loader according to the delegation model , If the load fails, the current loader will be loaded findClass Method to load , Therefore, our custom classloader only needs to inherit ClassLoader, And cover findClass Method  */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
    
        Class clazz = null;//this.findLoadedClass(name); //  Parent class loaded 
        //if (clazz == null) { // Check whether the class has been loaded 
        byte[] classData = getClassData(className(name));  // According to the binary name of the class , To obtain the class Bytecode array of file 
        if (classData == null) {
    
            throw new ClassNotFoundException();
        }
        // among defineClass Method can convert a file composed of binary stream bytes into a java.lang.Class
        clazz = defineClass(name,classData, 0, classData.length);  // take class The bytecode array of is converted to Class Class 
        return clazz;
    }

    // According to the binary name of the class , Get this from the network class Bytecode array of file 
    private byte[] getClassData(String name) {
    
        log.info(name);
        InputStream is = null;
        try {
    
            byte[] buff = new byte[1024*4];
            int len;
            URL url=new URL(this.classUrl+name+".class");
            is = url.openStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            while((len = is.read(buff)) != -1) {
    
                baos.write(buff,0,len);
            }
            return baos.toByteArray();
        } catch (Exception e) {
    
            e.printStackTrace();
        } finally {
    
            if (is != null) {
    
                try {
    
                    is.close();
                } catch(IOException e) {
    
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private String className(String name) {
    
        String[] split = name.split("\\.");
        return split[split.length-1];
    }

    public static void main(String[] args) {
    
        try {
    
            String rootUrl = "http://10.10.10.14:8080/localfile/com/";
            CustomClassLoader customClassLoader = new CustomClassLoader(rootUrl);
            String classname = "com.Hello";// Full class name 
            Class<?> clazz = customClassLoader.findClass(classname);
            log.info("ClassLoader:{} ", clazz.getClassLoader());  // Print class loader 
            Object newInstance = clazz.getDeclaredConstructor().newInstance();// Building objects 
            Method[] declaredMethods = clazz.getDeclaredMethods();
            for (Method m : declaredMethods) {
    
                m.invoke(newInstance);
            }
        } catch (Exception e) {
    
            e.printStackTrace();
        }
    }
}

 Insert picture description here

Reference article
Reference article

原网站

版权声明
本文为[cristianoxm]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/188/202207070422061990.html