关于自定义类加载器的问题

老王就是我 网站后台开发员  2021-05-08 11:49:15

public class CustomClassLoader extends ClassLoader {

@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
System.out.println(getSystemClassLoader());
String path = this.getClass().getResource("").getPath();
File file = new File(path.substring(0, path.indexOf("class") + 8) + name.replaceAll("\\.", "/") + ".class");
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
InputStreamReader fileInputStream = new InputStreamReader(new FileInputStream(file), StandardCharsets.ISO_8859_1);
// FileInputStream fileInputStream = new FileInputStream(file);
int b = 0;
while ((b = fileInputStream.read()) !=0) {
byteArrayOutputStream.write(b);
}
byteArrayOutputStream.close();
fileInputStream.close();
byte[] bytes = byteArrayOutputStream.toByteArray();
String s = new String(bytes);
System.out.println(s);
return super.defineClass(name, bytes, 0, bytes.length);
} catch (Exception e) {
e.printStackTrace();
}
return super.findClass(name);
}

public static void main(String[] args) {
CustomClassLoader customClassLoader = new CustomClassLoader();
try {
customClassLoader.loadClass("com.me.zookeeper.test.CustomClassLoader");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

当运行代码customClassLoader.loadClass("com.me.zookeeper.test.CustomClassLoader")时,没有调用自定义的findClass()方法
...全文
248 点赞 收藏 8
写回复
8 条回复
冰思雨 05月10日
引用 楼主 老王就是我 的回复:
当运行代码customClassLoader.loadClass("com.me.zookeeper.test.CustomClassLoader")时,没有调用自定义的findClass()方法
楼主忘记的 Java ClassLoader 的双亲委托机制吗? 一个类的加载过程,先是 parent 进行加载,如果 parent 加载不了,才是当前加载器进行加载。 之所以当前类没有进行加载,就是因为 parent 加载器已经加载完成了。 楼主,你把 com.me.zookeeper.test.CustomClassLoader 这个类的 class 文件放到另外路径当中,然后,findClass 里面去另外路径当中加载这个 class 文件,这样的话 parent 加载器就无法加载这个 class 文件了,然后,你自定义的加载器就可以进行加载了。
回复 点赞
老王就是我 05月10日
引用 8 楼 冰思雨 的回复:
[quote=引用 楼主 老王就是我 的回复:] 当运行代码customClassLoader.loadClass("com.me.zookeeper.test.CustomClassLoader")时,没有调用自定义的findClass()方法
楼主忘记的 Java ClassLoader 的双亲委托机制吗? 一个类的加载过程,先是 parent 进行加载,如果 parent 加载不了,才是当前加载器进行加载。 之所以当前类没有进行加载,就是因为 parent 加载器已经加载完成了。 楼主,你把 com.me.zookeeper.test.CustomClassLoader 这个类的 class 文件放到另外路径当中,然后,findClass 里面去另外路径当中加载这个 class 文件,这样的话 parent 加载器就无法加载这个 class 文件了,然后,你自定义的加载器就可以进行加载了。 [/quote] 哦哦,找到了,我是直接加载项目下的class
回复 点赞
KeepSayingNo 05月08日
这个应该不会吧,你打了断点吗
回复 点赞
老王就是我 05月08日
引用 5 楼 得一以生 的回复:
项目打完包之后,你要把Test.java这个文件从硬盘里对应目录com/me/zookeeper/test下移走
我换了一种方式,好像还是不行

public class CustomClassLoader extends ClassLoader {

    public void test(){
        System.out.println("测试加载是否完成");
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        System.out.println(getSystemClassLoader());
        String path = this.getClass().getResource("").getPath();
        File file = new File(name);
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            FileInputStream fileInputStream = new FileInputStream(file);
            int b = 0;
            while ((b = fileInputStream.read()) >-1) {
                byteArrayOutputStream.write(b);
            }
            byteArrayOutputStream.close();
            fileInputStream.close();
            byte[] bytes = byteArrayOutputStream.toByteArray();
            String s = new String(bytes);
            System.out.println(s);
            return super.defineClass(name, bytes, 0, bytes.length);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }

    public static void main(String[] args) {
        CustomClassLoader customClassLoader = new CustomClassLoader();
        try {
            Class<?> aClass = customClassLoader.loadClass("D:\\wok2\\zookeeper-test-main\\target\\classes\\com\\me\\zookeeper\\test\\Test.class");
            System.out.println(aClass.getClassLoader());
            System.out.println(aClass.getName());
            Test customClassLoader1 = (Test) aClass.newInstance();
            customClassLoader1.classLoaderRange();

        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }
}
回复 点赞
得一以生 05月08日
项目打完包之后,你要把Test.java这个文件从硬盘里对应目录com/me/zookeeper/test下移走
回复 点赞
老王就是我 05月08日
引用 2 楼 得一以生 的回复:
https://blog.csdn.net/weixin_30342639/article/details/105389653,类加载器的本质是jvm初始化时,加载类的引用,方法到栈内存,堆内存,和栈方法区里,比如说你自己写了一个xxxUtil类,你不希望AppClassLoader加载它,而是通过自定义加载器加载xxxUtil类,那就需要自己定义类加载器。 ------------------------------------------ 而你上述的写法是自己加载自己,那肯定是通过父类加载器加载了,而且还是在同一个类中运行,源码CustomClassLoader.java都在,不会进入自定义的加载器的,customClassLoader.loadClass("com.me.zookeeper.test.CustomClassLoader");这个loadClass是加载别人的
我换了一个类好像还是不行 Class<?> aClass = customClassLoader.loadClass("com.me.zookeeper.test.Test");
回复 点赞
得一以生 05月08日
https://blog.csdn.net/weixin_30342639/article/details/105389653,类加载器的本质是jvm初始化时,加载类的引用,方法到栈内存,堆内存,和栈方法区里,比如说你自己写了一个xxxUtil类,你不希望AppClassLoader加载它,而是通过自定义加载器加载xxxUtil类,那就需要自己定义类加载器。 ------------------------------------------ 而你上述的写法是自己加载自己,那肯定是通过父类加载器加载了,而且还是在同一个类中运行,源码CustomClassLoader.java都在,不会进入自定义的加载器的,customClassLoader.loadClass("com.me.zookeeper.test.CustomClassLoader");这个loadClass是加载别人的
回复 点赞
类加载器加载本类?
回复 点赞
发动态
发帖子
Java SE
创建于2007-09-28

3.4w+

社区成员

30.7w+

社区内容

Java 2 Standard Edition
社区公告
暂无公告