• 类加载


      类怎么加载的?当然就是通过ClassLoader加载的了。那具体是怎么加载的?这个就不是很清楚了。查了下资料才发现,具体加载模型有个名词,叫双亲委派。意思就是一个类加载器如果收到了加载请求,先找爸妈去加载,而不会自己做这件事。如果它爸妈收到儿女的委派,而且爸妈的爸妈还健在,那么爸妈也不能自己做主,接着请示爸妈的爸妈去加载。每一层加载器都必须先委派给父加载器,只有父加载器找不到要加载的类,才会由下一层加载器处理。我们来看图:

      不同加载器搜索的范围不同,启动类加载器只搜JAVA_HOMElib目录,扩展类加载器只搜JAVA_HOMElibext目录,应用程序类加载器只搜classpath目录。双亲委派的目的就是实现加载的优先级,避免同名类加载的混乱,避免通过自定义类加载器来恶意加载类达到替换标准API的目的。如果同一个class文件由不同的类加载器来加载,那么对应会有两个不同的实例。下面看下代码:

    package com.wulinfeng.io;
    
    import static java.lang.System.out;
    
    import java.io.InputStream;
    
    import sun.text.resources.cldr.FormatData;
    
    public class ClassLoad {
    
        public static void main(String[] args) throws Exception {
            // 加载一个在jre/lib/ext目录下的类FormatData.class
            Class clzEXT = FormatData.class;
            ClassLoader loader = clzEXT.getClassLoader();
            out.println("FormatData.class的类加载器:" + loader.getClass());
            out.println("FormatData.class的类加载器的父母:" + loader.getParent());
    
            // 加载一个在classpath下的类ClassLoad.class
            Class clzApp = ClassLoad.class;
            ClassLoader loader2 = clzApp.getClassLoader();
            out.println("ClassLoad.class的类加载器:" + loader2.getClass());
            out.println("ClassLoad.class的类加载器的父母:" + loader2.getParent());
            out.println("ClassLoad.class的类加载器的祖父母:" + loader2.getParent().getParent());
    
            // 自定义类加载器
            ClassLoader newLoader = new ClassLoader() {
                @Override
                public java.lang.Class<?> loadClass(String name) {
                    try {
                        String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
                        InputStream is = getClass().getResourceAsStream(fileName);
                        if (is == null) {
                            return super.loadClass(name);
                        }
                        byte[] b = new byte[is.available()];
                        is.read(b);
                        return defineClass(name, b, 0, b.length);
                    } catch (Exception e) {
                        System.err.println(e);
                    }
                    return null;
                }
            };
    
            out.println("自定义的类加载器:" + newLoader.getClass());
            out.println("自定义的类加载器的父母:" + newLoader.getParent());
            out.println("自定义的类加载器的祖父母:" + newLoader.getParent().getParent());
            // 使用自定义加载器加载ClassLoad.class,与application加载器得到的实例是不同的
            Object o = newLoader.loadClass("com.wulinfeng.io.ClassLoad").newInstance();
            out.println(o instanceof com.wulinfeng.io.ClassLoad);
        }
    }

      输出结果:

    FormatData.class的类加载器:class sun.misc.Launcher$ExtClassLoader
    FormatData.class的类加载器的父母:null
    ClassLoad.class的类加载器:class sun.misc.Launcher$AppClassLoader
    ClassLoad.class的类加载器的父母:sun.misc.Launcher$ExtClassLoader@33909752
    ClassLoad.class的类加载器的祖父母:null
    自定义的类加载器:class com.wulinfeng.io.ClassLoad$1
    自定义的类加载器的父母:sun.misc.Launcher$AppClassLoader@73d16e93
    自定义的类加载器的祖父母:sun.misc.Launcher$ExtClassLoader@33909752
    false
  • 相关阅读:
    构建之法 读书笔记01
    团队合作第一次会议有感
    浪潮之巅 读书笔记 03
    浪潮之巅 读书笔记 02
    团队介绍
    疫情查询app 开发
    世界疫情信息爬取 及开发查询爬取数据的app
    浪潮之巅 读书笔记 01
    支付宝沙箱配置
    定时器定时执行redis操作定时器执行几次自动停止的问题
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/6524696.html
Copyright © 2020-2023  润新知