三种类加载器(除自定义类加载器)
1.引导类加载器(BootstrapClassLoader):加载JAVA_HOME/lib下的类包
2.扩展类加载器(ExtClassLoader):加载JAVA_HOME/lib/ext 下的类包
3.应用程序类加载器(AppClassLoader):加载ClassPath路径下的类包
流程图
源码分析 launcher 的实例化流程
1.AppClassLoader 和 ExtClassLoader 都继承URLClassLoader
2.getLauncher() 获取的是一个 单例类 Launcher 对象,保证了每一个虚拟机只有一个 Launcher
3…程序执行的结果说明了 自定义类 User的 类加载器 是 AppClassLoader, AppClassLoader的父加载器是ExtClassLoader , ExtClassLoader 的父加载器是 null,下面源码解释一下为什么是这样**
###############################################################################
在Launcher的构造函数中,先创建ExtClassLoader 对象 var1,然后在创建AppClassLoader对象的时候将var1赋值给 AppClassLoader 的父加载器
###############################################################################
URLClassLoader 继承了 ClassLoader
###############################################################################
ClassLoader 构造函数中 初始化 父构造器 ClassLoader
###############################################################################
ExtClassLoader 的构造函数中会把 null 赋值给 parent
###############################################################################
而AppClassLoader 在初始化的时候会把 var2 也就是 ExtClassLoader 对象赋值给 parent
###############################################################################
4.注意 : 很多人看双亲委派原则都以为 AppClassLoader 的父类是 ExtClassLoader ,ExtClassLoader 的父类的 BootStrapClassloader,其实这是错的. 源码中我们可以看到 AppClassLoader 和 ExtClassLoader的父类都是URLClassLoader.我们说 AppClassLoader的父加载器是 ExtClassLoder ,ExtClassLoader的父加载器是BootStrapClassLoader,
下面讲双亲委派机制从源码上 来解释这一点 :
双亲委派机制原理
简单的说,就是子 类加载器 将加载任务丢给父加载器,父加载器加载不到了才返回给子加载器加载
双亲委派机制源码分析
上面流程图说到,类的加载都是 ClassLoader类的 loadClass函数
当我们执行一个main函数的时候 ,比如这一行
public static void main(String[] args) {
Math math = new Math();
math.excuteV();
}
步骤一:
步骤二:
步骤三:接着往下走
进入findClass函数,findClass函数是需要子类去实现的,因为AppClassLoader 和 ExtClassLoader 都继承URLClassLoader,所以我们进入 URLClassLoader 的 findClass函数
这个defineClass函数比较核心,是将Resource 资源 加载到类对象中
步骤四:
以上就实现了双亲委派机制
双亲委派机制的好处是啥呢?
1.可以防止重复加载数据 ,比如 AppClassLoader 加载了数据后 ExtClassLoader就不能加载相同数据了
2.沙箱安全机制:比如我自己写了一个跟 jdk一毛一样的类 都叫 java.lang.String ,这样 jvm只能由Bootstrap加载器加载到 jdk自带的java.lang.String ,而忽略掉自己写的 java.lang.String