您的位置:首页 > 其它

类加载器[3]自定义类加载器[1]:突破父类委托机制

2017-03-06 15:44 155 查看
 
如果要突破父类委托机制,需要重写loadClass()方法。
如下的例子,当遇到某个类名的时候,会先自己尝试加载,如果自己加载不到,再交由父加载器加载。
 Java Code 
 package com.bjsxt.test;

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

public class CustomClassLoader extends ClassLoader {

    private String rootDir;

    public CustomClassLoader(String rootDir) {

        this.rootDir = rootDir;

    }

    // 从ClassLoader复制过来修改
    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {//这里的ClassNotFoundException是有parent.loadClass()抛出的
        synchronized (getClassLoadingLock(name)) {

            // 判断当前类加载器是否已经加载该类
            Class<?> c = findLoadedClass(name);

            if (c == null) {// 未加载//尝试去加载

                c = findClass(name);

                if (c == null) {//加载不到,交由父加载器去加载
                    ClassLoader parent = getParent();

                    

                    if(parent!=null)

                        return parent.loadClass(name);//here
                }

            } // 已经加载

            if (resolve) {

                resolveClass(c);

            }

            

            return c;

        }

    }

    @Override

    protected Class<?> findClass(String name){

        // 从自定义目录读取文件,转化为一个字节数组
        byte[] classData = loadClassBytes(name);

        if (classData == null) {

            // throw new ClassNotFoundException();
            //这个地方就不再抛出异常了
            System.out.println("CustomClassLoader cannot load "+name+", try parent.");

            return null;

        } else {

            Class c = defineClass(name, classData, 0, classData.length);

            return c;

        }

    }

    private byte[] loadClassBytes(java.lang.String name) {

        String path = rootDir + "/" + name.replace(".", "/") + ".class";

        InputStream is = null;

        ByteArrayOutputStream baos = null;

        try {

            is = new FileInputStream(path);

            baos = new ByteArrayOutputStream();

            byte[] buffer = new byte[1024];

            int ret = 0;

            while ((ret = is.read(buffer)) != -1) {

                baos.write(buffer, 0, ret);

            }

            return baos.toByteArray();

        } catch (FileNotFoundException e) {

            e.printStackTrace();//这里输出FileNotFoundException
        } catch (IOException e) {

            e.printStackTrace();

        } finally {

            try {

                if (is != null)

                    is.close();

                if (baos != null)

                    baos.close();

            } catch (IOException e) {

                e.printStackTrace();

            }

        }

        return null;

    }

}
 
依然使用之前的HelloWorld.class来测试。



 
执行输出语句的时候,会遇到
java.lang.Object
java.lang.System
java.io.PrintStream
CustomClassLoader会先尝试加载,加载不到再交由父类加载器加载。(AppClassLoader,并回归正常机制。)
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: