美文网首页
自定义类加载器

自定义类加载器

作者: 半个橙子 | 来源:发表于2018-06-15 14:04 被阅读0次

https://blog.csdn.net/zhoudaxia/article/details/35824249
ClassLoader.loadClass(...) 是ClassLoader的入口点。当一个类没有指明用什么加载器加载的时候,JVM默认采用AppClassLoader加载器加载没有加载过的class,调用的方法的入口就是loadClass(...)。如果一个class被自定义的ClassLoader加载,那么JVM也会自动调用这个自定义的ClassLoader.loadClass(...)方法来加载class内部引用的一些别的class文件。

仿照Tomcat的类加载器写了一个加载器,不采用双亲委派,首先加载自己定义的类路径下的类,加载不到再让父加载器加载。
调用MyClassLoader类加载器来加载类BootClass,则BootClass中所有引用到的类jvm都会自动使用加载BootClass的类加载器MyClassLoader.loadClass来加载,而且这不是通过Thread.currentThread().setContextClassLoader()来实现的。》

image.png

MyClassLoader

package com.dongnao.TestClassloader;
import java.io.*;
public class MyClassLoader extends ClassLoader{
    private String classpath;
    public MyClassLoader(String classpath) {
        this.classpath = classpath;
    }
    /**
     * Jvm自动调用
     * 1.从手动设置的classpath路径加载
     * 2.如果没有加载到则从parent加载
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    public Class<?> loadClass(String name) throws ClassNotFoundException {
        System.out.println("--------------------loading "+name+"------------------");
        Class<?> aClass = findLoadedClass(name);
        if (aClass!=null){
            //System.out.println("-----Have loaded-----");
            return aClass;
        }
        aClass = findClass(name);
        if (aClass==null&&getParent()!=null){
            //System.out.println("------Give parent-----");
            aClass = getParent().loadClass(name);
        }
        //System.out.println("-------------Finish "+aClass+"---------------");
        return aClass;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
            byte [] classData=getData(name);
            if(classData==null) {
                return null;
            }else {
                //defineClass方法将字节码转化为类
                return defineClass(name,classData,0,classData.length);
            }
    }

    //返回类的字节码
    private byte[] getData(String className){
        InputStream in = null;
        ByteArrayOutputStream out = null;
        String path=classpath + File.separatorChar +
                className.replace('.',File.separatorChar)+".class";
        try {
            in=new FileInputStream(path);
            out=new ByteArrayOutputStream();
            byte[] buffer=new byte[2048];
            int len=0;
            while((len=in.read(buffer))!=-1){
                out.write(buffer,0,len);
            }
            return out.toByteArray();
        }
        catch (IOException e) {
        }
        finally{
            try {
                if (in!=null)
                in.close();
            } catch (IOException e) {
                //e.printStackTrace();
            }
            try {
                if (out!=null)
                out.close();
            } catch (IOException e) {
                //e.printStackTrace();
            }
        }
        return null;
    }
}

TestClassLoader

package com.dongnao.TestClassloader;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class TestClassLoader {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        System.out.println("Bootstrap ClassLoader:"+ClassLoader.getSystemClassLoader().getParent().getParent());
        System.out.println("Extension ClassLoader:"+ClassLoader.getSystemClassLoader().getParent());
        System.out.println("java.ext.dirs"+System.getProperty("java.ext.dirs"));
        System.out.println("Application ClassLoader:"+ClassLoader.getSystemClassLoader());
        System.out.println("java.class.path:"+System.getProperty("java.class.path"));

        MyClassLoader myClassLoader = new MyClassLoader("out/production/basicsDemo/");
        //调用MyClassLoader类加载器来加载类BootClass,
        //则BootClass中所有引用到的类jvm都会自动使用BootClass的类加载器MyClassLoader.loadClass来加载
        Class<?> testCase = myClassLoader.loadClass("com.dongnao.TestClassloader.App.BootClass");
        Method startMethod = testCase.getMethod("start", null);
        Object o = testCase.newInstance();
        startMethod.invoke(o,null);
    }
}

Reuslt

Bootstrap ClassLoader:null
Extension ClassLoader:sun.misc.Launcher$ExtClassLoader@1055e4af
java.ext.dirs:S:\Java\jre\lib\ext;C:\WINDOWS\Sun\Java\lib\ext
Application ClassLoader:sun.misc.Launcher$AppClassLoader@18b4aac2
java.class.path:S:\Java\jre\lib\charsets.jar;S:\Java\jre\lib\deploy.jar;S:\Java\jre\lib\ext\access-bridge-64.jar;S:\Java\jre\lib\ext\cldrdata.jar;S:\Java\jre\lib\ext\dnsns.jar;S:\Java\jre\lib\ext\jaccess.jar;S:\Java\jre\lib\ext\jfxrt.jar;S:\Java\jre\lib\ext\localedata.jar;S:\Java\jre\lib\ext\nashorn.jar;S:\Java\jre\lib\ext\sunec.jar;S:\Java\jre\lib\ext\sunjce_provider.jar;S:\Java\jre\lib\ext\sunmscapi.jar;S:\Java\jre\lib\ext\sunpkcs11.jar;S:\Java\jre\lib\ext\zipfs.jar;S:\Java\jre\lib\javaws.jar;S:\Java\jre\lib\jce.jar;S:\Java\jre\lib\jfr.jar;S:\Java\jre\lib\jfxswt.jar;S:\Java\jre\lib\jsse.jar;S:\Java\jre\lib\management-agent.jar;S:\Java\jre\lib\plugin.jar;S:\Java\jre\lib\resources.jar;S:\Java\jre\lib\rt.jar;H:\动脑Java\高并发分布式(专题三)\052-面试专题(Java基础)-20180206-Five\basicsDemo\out\production\basicsDemo;C:\Program Files\JetBrains\IntelliJ IDEA 2018.2.3\lib\idea_rt.jar;C:\Users\pengyunlong\.IntelliJIdea2018.2\system\captureAgent\debugger-agent.jar
--------------------loading com.dongnao.TestClassloader.App.BootClass------------------
--------------------loading java.lang.Object------------------
--------------------loading java.lang.System------------------
--------------------loading java.lang.StringBuilder------------------
--------------------loading java.lang.Class------------------
--------------------loading java.io.PrintStream------------------
BootClass:com.dongnao.TestClassloader.MyClassLoader
--------------------loading com.dongnao.TestClassloader.App.Biz------------------
>>>>>>>>>>>>>>>>>>>ClassLoaderInfo<<<<<<<<<<<<<<<<<<<<<<
Biz:com.dongnao.TestClassloader.MyClassLoader
Object:null
--------------------loading java.lang.Thread------------------
ContextClassLoader:sun.misc.Launcher$AppClassLoader
--------------------loading com.dongnao.TestClassloader.App.User------------------
Hello,my name is Bob
User:com.dongnao.TestClassloader.MyClassLoader@e6ea0c6
package com.dongnao.TestClassloader.App;
public class BootClass {
    public void start(){
        System.out.println("BootClass:"+this.getClass().getClassLoader().getClass().getName());
        new Biz().echo();
    }
}

package com.dongnao.TestClassloader.App;
public class Biz {
    public void echo(){
        System.out.println(">>>>>>>>>>>>>>>>>>>ClassLoaderInfo<<<<<<<<<<<<<<<<<<<<<<");
        System.out.println("Biz:"+this.getClass().getClassLoader().getClass().getName());
        System.out.println("Object:"+new Object().getClass().getClassLoader());
        System.out.println("ContextClassLoader:"+Thread.currentThread().getContextClassLoader().getClass().getName());
        User user = new User("Bob",10);
        user.sayHello();
        System.out.println("User:"+user.getClass().getClassLoader());
    }
}

package com.dongnao.TestClassloader.App;
public class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public void sayHello(){
        System.out.println("Hello,my name is "+name);
    }
}

相关文章

网友评论

      本文标题:自定义类加载器

      本文链接:https://www.haomeiwen.com/subject/vhqmeftx.html