A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 月落 初级黑马   /  2019-5-31 11:02  /  628 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

类加载器

              1.加载: 取得类的二进制流,2.转为方法区数据结构,3.在Java堆中生成对应java.lang.Class对象

              3.准备:分配内存,并为类的静态变量设置默认初始值 (方法区中),注意:此时对象并未创建,且常量在该阶段就完成赋值,解析:符号引用替换为直接引用   1)、符号引用:Java中,一个java类将会编译成一个class文件。在编译时,java类并不知道所引用的类的实际地址,因此只能使用符号引用来代替。比如org.simple.People类引用了org.simple.Language类,在编译时People类并不知道Language类的实际内存地址2)、直接引用:、实际内存地址,指向了实际的内存如果有了直接引用,那引用的目标必定已经被加载入内存中了。

初始化:执行类构造器 1、static变量 赋值语句 2、static{}语句 3、子类的调用前保证父类的被调用 4、是线程安全的

   – 访问某个类或接口的静态变量,或者对该静态  变量赋值

   – 反射(如Class.forName(“java.lang.String”)

   – Java虚拟机启动时被标明为启动类的类(Java Test)

   BootStrap ClassLoader (启动ClassLoader,根类加载器) rt.jar  java.lang   Extension ClassLoader (扩展ClassLoader)  ext包下的 内容   App ClassLoader (应用ClassLoader/系统ClassLoader) 开发人员自己写的   Custom ClassLoader(自定义ClassLoader)   根类加载器并不是由Java代码写的,且sun公司也不提供对根类加载器的任何操作,想要拿到这个一个加载器,返回的结果是null除了根类加载器以外,其他的加载器都是java代码写的,上一层是下一层的父容器 ,值得注意的是他们并不是一个继承关系,而是逻辑上的父子关系   启动类加载器,由C++实现,没有父类。   拓展类加载器(ExtClassLoader),由Java语言实现,父类加载器为BootStrap   系统类加载器(AppClassLoader),由Java语言实现,父类加载器为ExtClassLoader   自定义类加载器,父类加载器肯定为AppClassLoader。

   原理:如果一个类加载器收到了类加载请求,它并不会自己先去加载,而是把这个请求委托给父类的加载器去执行,如果父类加载器还存在其父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器,如果父类加载器可以完成类加载任务,就成功返回,倘若父类加载器无法完成此加载任务,子加载器才会尝试自己去加载,这就是双亲委派模式,

   双亲机制的目的:防止对象的重复加载!   举例:每个类加载器都能加载对应不同文件的类,那么假如我们自己定义了一个java.lang.Object包下的内容,那么首先这个类是我们自己写的,也存在我们的classpath路径下,会被app加载器加载,但同样,JDK中的Object也会被加载,产生多个对象,造成混乱!

        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 {
                             //如果找不到,则委托给父类加载器去加载
                            if (parent != null) {
                                 c = parent.loadClass(name, false);
                             } else {
                                  //如果没有父类,则委托给启动加载器去加载
                                c = findBootstrapClassOrNull(name);
                             }
                         } catch (ClassNotFoundException e) {
                         }
                         }
            而对应findClass是在CLassloader接口中用于给子类重写使用的源码中只是一个空实现

双亲委派模型的破坏者   介绍:打破双亲委派机制有3种方式,双亲委派的核心是由下向上委托,而所谓的打破,指的是在加载资源时需要从上往下寻找

    2.热部署,热部署会使得每个点都具有一个类加载器,从而使得类加载器形成一个网状结构,从而打破了双亲委派机制

       线程类上下文类加载器是调用java.lang.Thread 包下的getContextClassLoader 和setContextClassLoader-->如果没有设置的话默认就是appClassLoader

了解一个类的的加载过程,可以帮助我们理解底层的原理,通过这堂课的学习,相信同学们一定对于学习类加载器有了一定的了解,谢谢各位同学

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马