通过类加载器ClassLoader
二:类加载器有四种类型1.Bootstrap ClassLoader
Bootstrap类加载器是用来加载java核心类库的,即%JRE_HOME%lib下的jar包,包括rt.jar,resource.jar,charset.jar等,jvm一旦启动,就会默认去加载这些基础类到内存中,保证程序的正常运行
2.Extension ClassLoader
Extension类加载器是用来加载java核心类库的,加载%JRE_HOME%ext下的jar包
3.Application ClassLoader
主要负责加载当前应用的classpath下的所有类
4.User ClassLoader
用户自定义的类加载器,可直接指定路径的class文件
三:双亲委派机制1.原理说明
把上述四个类加载器看成是继承关系(实质不是继承关系。而是组合关系),则Bootstrap ClassLoader是最顶层的加载器,接下来分别是Extension ClassLoader,Application ClassLoader,User ClassLoader。所谓双亲委派机制,就是加载一个类,优先使用父加载器,当父加载器无法加载类时,才用子类加载器加载。比如Integer类,会优先使用BootStrap类加载器来加载,当无法加载时,才会轮到Extension ClassLoader,一直轮到User ClassLoader。
2.为什么需要双亲委派机制
一个最大的原因就是为了保证安全。有了双亲委派机制,就可以保证系统类不会被破坏
比如自定义了一个java.lang包下的Integer类,若没有双亲委派机制,Application ClassLoader会加载该自定义的类,那么系统的Integer类就不会被加载,也就是相当于被破坏了。有了双亲委派机制,类的加载就相当于有了优先级,也就是优先保护系统的类,即优先加载系统的类
另外一个重要原因是为了避免重复加载。jvm判断一个是否是同一个class的原则是全类名+类加载器。其实就是相当于先问问大哥们是否有加载,如果没有自己就加载,避免大哥们加载了,自己又再次加载的情况
四:打破双亲委派机制类加载除了双亲委派机制,还有全盘负责机制。也就是说,当某个类使用了特定的类加载加载后,该类所引用的所有依赖,都会使用该类加载器来加载,若加载不到,则抛出异常。因此,想要加载一些系统类的第三方实现,就需要打破该机制
1.例子1:jdbc
通常情况下都是使用DriverManager.getConnection()来获取数据库连接,DriverManager是系统类,会使用BootstrapClassLoader来加载,但是加载这个类时,会执行这个类的静态代码块,进而加载Driver接口下的实现类(SPI)。但是该接口是由第三方提供的,如mysql-connector下的Driver,就是Driver接口的实现类,但是第三方的jar包,BootStrap ClassLoader是加载不到的,因此使用了SPI的方式来加载(通过指定线程上下文ClassLoader去加载),直接加载类路径下对应接口的实现类
2.例子2:自定义类加载器,重写loadClass()方法
类加载器的双亲委派机制都存放在ClassLoader类的loadClass()方法中,通过重写该方法,就可以自定义加载类的逻辑,破坏双亲委派机制。
注意:若想自定义类加载器的加载逻辑,但是又不想破坏双亲委派机制,可以通过选择重写findClass()来实现。因为loadClass的逻辑是父类加载失败,就会调用自己的findClass()来加载



