8 类加载器

image-20230325232116984

加载类的时候会先询问上级的类加载器是否加载过了

8.1 启动类加载器

image-20230325232516456

这样,该类会由BootStrap类加载器加载 打印会出现null因为启动类加载器是由C++写的

image-20230325232858561

8.2 拓展类加载器

image-20230325233250960

用jar -cvf my.jar com.....\xx.class 打包jar包,然后放到jdk的jre\lib\ext下

这样拓展加载器就会在他的类路径下找到该类,此时APP加载器不能加载该类,而是由扩展加载器来加载,也称为双亲委派,委派上级优先做一个类的加载

8.3 双亲委派模式

image-20230325233731790

用递归查找

5.4 线程上下文类加载器

在使用JDBC时,都需要加载Driver驱动

Class.forName("com.mysql.jdbc.Driver")

其中的源码:

image-20230326000259199

private static void loadInitialDrivers() {
        String drivers;
        try {
            drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {
                public String run() {
                    return System.getProperty("jdbc.drivers");
                }
            });
        } catch (Exception ex) {
            drivers = null;
        }

		//使用ServiceLoader 机制加载驱动 即SPI
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {

                ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);
                Iterator<Driver> driversIterator = loadedDrivers.iterator();

        
                try{
                    while(driversIterator.hasNext()) {
                        driversIterator.next();
                    }
                } catch(Throwable t) {
                // Do nothing
                }
                return null;
            }
        });

        println("DriverManager.initialize: jdbc.drivers = " + drivers);

    	//使用jdbc.dervers定义的驱动名加载驱动
        if (drivers == null || drivers.equals("")) {
            return;
        }
        String[] driversList = drivers.split(":");
        println("number of Drivers:" + driversList.length);
        for (String aDriver : driversList) {
            try {
                println("DriverManager.Initialize: loading " + aDriver);
                //getSystemClassLoader就是APPClassLoader
                Class.forName(aDriver, true,
                        ClassLoader.getSystemClassLoader());
            } catch (Exception ex) {
                println("DriverManager.Initialize: load failed: " + ex);
            }
        }
    }
在jre/lib包下有一个DriverManager,是启动类加载的,但是jdbc的驱动是各个厂商来实现的不在启动类加载路径下,启动类无法加载,而驱动管理需要用到这些驱动
只能打破双亲委派,启动类直接请求系统类加载器去classpath下加载驱动(正常是向上委托,这个反过来了),而打破双亲委派的就是这个线程上下文类加载器
过程就是:启动类加载器加载DriverManager,DriverManager代码里调用了线程上下文类加载器,这个加载器默认就是使用应用程序类加载器加载类,通过应用程序类加载器加载jdbc驱动

image-20230326002011248

image-20230326002328182

image-20230326002400584

image-20230326003603896

8.5 自定义类加载器

image-20230326003631538

自定义类加载器

image-20230326004526289

 posted on 2023-03-27 22:17    阅读(21)  评论(0编辑  收藏  举报