Java 自定义ClassLoader

双亲委派模型

不是继承关系,是组合关系. 子加载器拥有父加载器的实例

加载流程,如下:
1. 当前类加载器首先查询该类是否已加载, 若没加载,则跳(2)
2. 委托父加载器加载,父加载器执行相同的操作,如加载失败,则跳(3)
3. 使用启动类加载器加载, 若报错,则跳(4)
4. 使用自身去加载,若报错,则加载失败

[1,2,3]的实现在ClassLoader#loadClass方法中

[4]的实现在ClassLoader#findClass方法中

系统类加载器

BootStrap ClassLoader

加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类

Extension ClassLoader

加载$JAVA_HOME中jre/lib/ext/*.jar或-Djava.ext.dirs指定目录下的jar包

App ClassLoader

加载CLASSPATH或-Djava.class.path所指定的目录下的类和jar包

自定义加载器

遵循 双亲委派模型

只需重写ClassLoader#findClass

public class MyClassLoader extends ClassLoader {

    private String path = null;

    public MyClassLoader(String path) {
        this.path = path;
    }

    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        try {
            byte[] bytes = loadByte(name);
            return defineClass(name, bytes, 0, bytes.length);
        } catch (Exception e) {
            throw new ClassNotFoundException("类找不到" + name);
        }
    }

    private byte[] loadByte(String name) throws Exception {
        String fileName = path + File.separator + replaceSeparator(name) + ".class";

        try (FileInputStream fis = new FileInputStream(fileName)) {
            byte[] data = new byte[fis.available()];
            fis.read(data);
            return data;
        } catch (Exception e) {
            throw e;
        }
    }

    private String replaceSeparator(String name) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < name.length(); i++) {
            if (name.charAt(i) != '.') {
                sb.append(name.charAt(i));
            } else {
                sb.append(File.separator);
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader("/home/wyj");
        Runtime.getRuntime().exec("javac /home/wyj/Test.java");
        Class test = classLoader.loadClass("Test");
        System.out.println(test.getClassLoader());
    }
}

不遵循 双亲委派模型

public class MyClassLoader extends ClassLoader {

    private String path = null;

    public MyClassLoader(String path) {
        this.path = path;
    }

    @Override
    public Class loadClass(String name) throws ClassNotFoundException {
        Class clazz = null;

        clazz = findLoadedClass(name);
        if (clazz == null) {
            try {
                clazz = findClass(name);
            } catch (Exception e) {
            }
        }

        if (clazz == null) {
            clazz = super.loadClass(name);
        }
        return clazz;
    }

    @Override
    protected Class findClass(String name) throws ClassNotFoundException {
        try {
            byte[] bytes = loadByte(name);
            return defineClass(name, bytes, 0, bytes.length);
        } catch (Exception e) {
            throw new ClassNotFoundException("类找不到" + name);
        }
    }

    private byte[] loadByte(String name) throws Exception {
        String fileName = path + File.separator + replaceSeparator(name) + ".class";

        try (FileInputStream fis = new FileInputStream(fileName)) {
            byte[] data = new byte[fis.available()];
            fis.read(data);
            return data;
        } catch (Exception e) {
            throw e;
        }
    }

    private String replaceSeparator(String name) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < name.length(); i++) {
            if (name.charAt(i) != '.') {
                sb.append(name.charAt(i));
            } else {
                sb.append(File.separator);
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader("/home/wyj");
        Runtime.getRuntime().exec("javac /home/wyj/Test.java");
        Class test = classLoader.loadClass("Test");
        System.out.println(test.getClassLoader());
    }
}

Test.java

public class Test {
}

使用场景

遵循

不遵循

你可能感兴趣的:(java)