类加载顺序图:
这样做的好处就是:Java类随着它的类加载器一起具备了一种带有优先级的层次关系。例如类java.lang.Object,它存放在rt.jar中,无论哪一个类加载器要加载这个类,最终都是委派给处于模型最顶端的启动类加载器进行加载,因此Object类在程序的各种类加载器环境中都是同一个类。相反,如果没有使用双亲委派模型,由各个类加载器自行去加载的话,如果用户自己编写了一个称为java.lang.object的类,并放在程序的ClassPath中,那系统中将会出现多个不同的Object类,Java类型体系中最基础的行为也就无法保证,应用程序也将会变得一片混乱。
其次是考虑到安全因素。假设通过网络传递一个名为java.lang.Integer的类,通过双亲委托模式传递到启动类加载器,而启动类加载器在核心Java API发现这个名字的类,发现该类已被加载,并不会重新加载网络传递的过来的java.lang.Integer,而直接返回已加载过的Integer.class,这样便可以防止核心API库被随意篡改。JDBC为何要破坏双亲委派模型?
在JDBC 4.0后,使用数据库驱动程序,我们不在需要Class.forName来加载驱动程序,只需要把驱动的jar包放到工程的类加载路径中,驱动程序就会自动被加载。这得益于Java中的SPI技术,只需要将加载的类名称放在META-INF/services目录下的java.sql.Driver文件中,即可自动进行加载。在使用上,我们只需下面一行代码就可以创建数据库连接。Connection con = DriverManager.getConnection(url , username , password ) ;因为类加载器收到加载范围的限制,在某些情况下父加载器无法加载到需要的文件,就需要委托给子类加载器去加载class文件。 JDBC的Driver接口定义在JDK中,其实现由数据库的各个厂商提供。DriverManager类中要加载各个实现了Driver接口的类统一进行管理,Driver类位于JAVA_HOME中jre/lib/rt.jar中,应该由Bootstrap类加载器进行加载,而各个Driver的实现类位于各个服务商提供的jar包中。根据类加载机制,当被加载的类引用了另外一个类时,虚拟机就会使用装载第一个类(先加载父类)的类加载器装载被引用的类,也就是说应该使用Bootstrap类加载器去加载各个厂商提供的Driver类。但是,Bootstrap类加载器只负责加载JAVA_HOME中jre/lib/rt.jar中所有的class,所以需要由子类加载器去加载Driver的实现类,这就破坏了双亲委派模型。 查看DriverManager类的源码,看到在使用DriverMnager的时候回触发器静态代码块,调用loadInitialDrivers()方法,并调用ServiceLoader.load(Driver.class)加载所有在META-INF/Services/java.sql.Driver文件中的类到JVM内存,完成驱动的自动加载。
static { loadInitialDrivers(); println("JDBC DriverManager initialized"); } private static void loadInitialDrivers() { 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; } }); }子类的类加载器是通过Thread.currentThread().getContextClassLoader()得到的线程上下文加载器。
public static <S> ServiceLoader<S> load(Class<S> service) { ClassLoader cl = Thread.currentThread().getContextClassLoader(); return ServiceLoader.load(service, cl); }
标签:委派,java,jar,Driver,class,SPI,双亲,ServiceLoader,加载 From: https://www.cnblogs.com/zhengbiyu/p/17234162.html