我们都知道,jvm执行的代码,都是通过jvm加载系统加入的。加载系统的第一步是通过ClassLoader加载class二进制信息,jvm规范中并没有规定class的来源类型,这就给jvm的实现这块很大的灵活。可以放在数据库里,可以放在网络的其他地方(以前的applet),zip文件等。现在大多数都是放在zip包里,我们引入其他class都是通过引入zip包的形式。
 
   ClassLoader关系结构如下
          BootStrap ClassLoader
               |
          Extension ClassLoader
               |
          System ClassLoader
               |
          Custom  ClassLoader
 
BootStrap ClassLoader 是由C++编写,虚拟机的一部分,只用来加载核心类。负责加载目录[JAVA_HOME]/bin下的jar,或者被参数 -DXbootclasspath说指定目录的jar,并且是jvm识别的。
 
Extension ClassLoader是java编写的,对应java系统中的ExtClassLoader类,负责加载java里的ext包里的类。
 
System ClassLoader 也是由java编写,对应系统中的AppClassLoader类,负责加载应用中的代码。
 
Custom ClassLoader是自己定义的ClassLoader,同AppClassLoader类,不同的事,他限定了只加载一部分应用中的代码。
 
ClassLoader的双亲委派模型
 
     双亲委派模型,主要是整理java加载的秩序性,限定核心,扩展类的重复加载。
 
    BootStrap ClassLoader  —>  Extension ClassLoader  —> System ClassLoader —> Custom ClassLoader 的父子关系,是由组合关系组成的。加载类时,先请求parent加载器,如果加载成功就返回;否则自己再作加载。这样有个好处是核心jar类或者扩展jar类可以做到唯一性,不会每个ClassLoader都加载他。
 
 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // 查找class是否被加载
            Class<?> c = findLoadedClass(name);
            if (c == null) {
                long t0 = System.nanoTime();
                try {
                   // 先让父加载ClassLoader加载类
                    if (parent != null) { 
                        c = parent.loadClass(name, false);
                    } else {
                       // 启动类ClassLoader加载
                        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
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }
 
从方法中,我们看到,ClassLoader先判断类有没有被加载,如果有直接返回;如果没有在请求父ClassLoader,父ClassLoader在递归相同的操作;如果父ClassLoader为null,表面为启动类加载器,换成启动类加载器加载;如果还没加载,在伦到自己加载。
 
从方法的修饰词 protected 可以看出,ClassLoader的双亲模式是不牢靠的,只要自定义的ClassLoader重载这个方法,就可能破坏双亲委派模型。
 

ClassLoader心得的更多相关文章

  1. 金三银四背后,一个 Android 程序员的面试心得

    回顾一下自己这段时间的经历,九月份的时候,公司通知了裁员,我匆匆忙忙地出去面了几家,但最终都没有拿到offer,我感觉今年的寒冬有点冷.到十二月份,公司开始第二波裁员,我决定主动拿赔偿走人.后续的面试 ...

  2. 我的MYSQL学习心得(一) 简单语法

    我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  3. NoSql数据库使用半年后在设计上面的一些心得

    NoSql数据库这个概念听闻许久了,也陆续看到很多公司和产品都在使用,优缺点似乎都被分析的清清楚楚.但我心里一直存有一个疑惑,它的出现究竟是为了解决什么问题? 这个疑惑非常大,为此我看了很多分析文章, ...

  4. 我的MYSQL学习心得(二) 数据类型宽度

    我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  5. 我的MYSQL学习心得(三) 查看字段长度

    我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(五) 运 ...

  6. 我的MYSQL学习心得(四) 数据类型

    我的MYSQL学习心得(四) 数据类型 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(五) 运 ...

  7. 我的MYSQL学习心得(五) 运算符

    我的MYSQL学习心得(五) 运算符 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  8. 我的MYSQL学习心得(六) 函数

    我的MYSQL学习心得(六) 函数 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

  9. 我的MYSQL学习心得(七) 查询

    我的MYSQL学习心得(七) 查询 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据类 ...

随机推荐

  1. git常用命令总结——覆盖日常开发全操作

    前言:Git是目前世界上最先进的分布式版本控制系统,对的,最先进! 1. 版本库,又名仓库,repository 可理解成一个目录,目录里的所有文件都可被Git管理,Git可以跟踪每个文件的修改.删除 ...

  2. Design Phone Directory

    Design a Phone Directory which supports the following operations: get: Provide a number which is not ...

  3. GridControl gridView显示筛选行,设置条件为包含

    public static void SetFilter(GridView gdv) {     gdv.OptionsView.ShowAutoFilterRow = true; //设置筛选行  ...

  4. 基于Docker 搭建 Jenkins

    ⒈下载镜像 要使用最新的LTS: docker pull jenkins/jenkins:lts 要使用最新的每周 docker pull jenkins/jenkins ⒉运行 docker run ...

  5. Codeforces Round #225 (Div. 1) C. Propagating tree dfs序+ 树状数组或线段树

    C. Propagating tree Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/383/p ...

  6. Python学习7——异常

    编写程序时,通常能够区分正常和异常情况.为了处理这些异常,可在每个可能出现异常的地方都使用上条件语句,但这样大大降低了程序的可读性,那么怎么解决哪?Python提供强大的替代解决方案——异常处理机制. ...

  7. Linux试题亿点点

    1. 在登录Linux时,一个具有唯一进程ID号的shell将被调用,这个ID是什么(b) A.NID B.PID C.UID C.CID # process ID 进程id号 # UID 用户iD号 ...

  8. url编码问题小计

    昨天通过get访问服务器遇到了服务器获取不到参数的问题,最后排查下来是因为url编码的原因,之前使用的是字符串拼接,所以有一些特殊字符如‘%’没有正确的编码, 通过改成各个部分编码,正确获取到数据. ...

  9. Spring实战(七)Bean 的作用域

    1.Spring中bean 的多种作用域 单例(Singleton):整个应用中只创建一个bean 的实例,Spring默认创建单例的bean: 原型(Prototype):每次注入or通过Sprin ...

  10. Fabric的简介

    1,初识fabric 1,什么是fabric fabric是一个Python的库和命令行工具,用来提高基于SSH的应用部署和系统管理的效率. 简单来说: (1)一个让你通过命令行执行无参数python ...