-
类加载器
(1) 作用:通过一个类的全限定名获取类的二进制字节流
(2) 类的唯一性由__类加载器__和__类__本身 一起保证
即便采用了单例模式,如果类加载器不同,加载出的两个类的对象也不同
-
类加载器的分类
(1) 分类一
1° 启动类加载器
用C++编写,是JVM的一部分,负责将/lib中的类库加载到虚拟机内存中,无法被Java程序直接引用
2° 其他类加载器
用java编写
(2) 分类二
1° 启动类加载器
同 (1) 1°
2° 扩展类加载器
负责加载/lib/ext中的类库,开发者可以直接使用
3° 应用程序类加载器
是ClassLoader类的静态方法getSystemClassLoader()的返回值,负责加载__用户类路径(classpath)__上的类库。
如果开发者没有自定义类加载器,这个就是默认的类加载器
4° 自定义类加载器
自己编写的ClassLoader的实现类
-
双亲委派模型
(1) 类加载器的层次结构
启动类加载器 ^ | | 扩展类加载器 ^ | | 应用程序类加载器 ^ ^ | | | | 自定义类加载器1 自定义类加载器2 ...
(2) 工作过程
1° 任何一个类加载器收到了类加载的请求,它都先__委托给自己的上层__父加载器加载(这是个递归调用的过程),直到最上层的启动类加载器
2° 如果上层的加载器成功加载,那就结束;如果上层加载器加载失败,再由自己加载
(3) 好处
防止同一个底层类被不同类加载器加载的情况
例如现在有两个自定义类加载器,它们每个都要加载Object类。如果不采用双亲委派模型,都是自己就加载,那Object类会出现两套;现在的情况是它们都逐级向上最终交给启动类加载器去加载,这样只出现了一套Object类
(4) 双亲委派模型的实现很简单,就是照着上面的思路,在ClassLoader类有实现
ClassLoader.java protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // ClassNotFoundException thrown if class not found // from the non-null parent class loader } if (c == null) { // If still not found, then invoke findClass in order // to find the class. long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats PerfCounter.getParentDelegationTime().addTime(t1 - t0); PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
chapter07_虚拟机类加载机制_4_类加载器
最新推荐文章于 2024-08-05 00:14:24 发布