ClassLoader

类从加载到虚拟机内存开始,到卸载出内存,它的整个生命周期包括:加载(loading)、验证(verification)、准备(preparation)、解析(resolution)、初始化(initialization)、使用(using)、卸载(unloading)7个阶段。其中验证、准备、解析3个部分统称为链接(linking)java

 

JVM规范规定有且仅有下面5种状况会触发类的初始化(加载、验证、准备在这以前完成):spa

  1. 遇到new、getstatic、putstatic、invokestatic这4个字节码命令时,若是累没有进行过初始化,则须要先触发其初始化。这4条命令对应的场景:使用new关键字实例化对象、读取或设置一个类的静态变量(被final修饰、已在编译期把结果放入常量池的除外),以及调用静态方法的时候。
  2. 使用java.lang.reflect包的方法对类进行反射调用的时候,若是类没有加载过
  3. 当初始化一个类当其父类没有初始化过,则先初始化父类
  4. 当虚拟机启动,会先初始化main方法主类
  5. 当使用JDK 7的动态语言支持时,若是一个java.lang.invoke.MethodHandle实例最后解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,而且这个方法句柄所对应的类没有进行过初始化,则须要先触发其初始化

 

接口的初始化与类初始化相似,只有3.不一样,父类接口只在用到时候才会初始化设计

 

 

ClassLoader类加载器,主要的做用对象

  1. 负责将Class加载到JVM中;
  2. 审查每一个类应该由谁加载;
  3. 将Class字节码从新解析成JVM统一要求的对象格式;

 

ClassLoader的几个主要方法:继承

  1. defineClass(byte[], int, int)用来将byte字节流解析成JVM可以识别的Class对象
  2. resolveClass(Class<?>)用来链接(Link)类
  3. findClass(String)用来实现类的加载规则,从而取得加载类的字节码。而后能够结合defineClass方法生成类的Class对象,若是想在类被加载到JVM中时就被链接,能够接着调用resolve方法。
  4. loadClass(String)中会调用findClass方法,默认不调用resolve方法,能够同太重载方法loadClass(String,boolean)在类加载到JVM是被连接,否则将在对象真正实力化时才进行连接

 

ClassLoader是一个抽象类,它有不少子类,咱们若是要实现本身的ClassLoader,通常都会继承URLClassLoader这个子类,由于这个类已经帮咱们实现了大部分工做。接口

 

整个JVM中提供了三个ClassLoader类,这三个ClassLoader能够分为两种类型,加载JVM自身工做须要类的加载器和为其余类服务的加载器:生命周期

  1. Bootstrap ClassLoader,这个ClassLoader主要加载JVM自身工做须要的类,这个ClassLoader彻底是JVM本身控制,因此不遵照双亲委托接待(Parents Delegation Model)规则。将%JAVA_HOME%\lib路径下或-Xbootclasspath参数指定路径下的、能被虚拟机识别的类库(仅按照文件名识别,如:rt.jar,名字不符合的类库不会被加载)加载至虚拟机内存中
  2. ExtClassLoader,用来加载System.getProperty("java.ext.dirs")目录下的类,(默认值是%JAVA_HOME%\jre\lib\ext,可由VM参数-Djava.ext.dirs指定)
  3. AppClassLoader,继承自ExtClassLoader,这个类加载器用来加载System.getProperty("java.class.path")目录下的类默认值是系统环境变量classpath的值,可由VM参数-Djava.class.path指定),这个目录就是咱们经常使用的classpath

 

ExtClassLoader和AppClassLoader都位于sun.misc.Launcher类中,都是Launcher类的内部类。内存

 

ClassLoader分为不一样的等级,为了保证每一个类只能在某个级别的ClassLoader被加载一次,ClassLoader设计出了双亲委托接待(Parents Delegation Model),规则以下:get

若是一个类加载器收到了加载类的请求,首先检查这个类是否已经被当前加载器加载过,若是没加载过它首先不会本身去尝试加载这个类,而是把这个请求委托给上级类加载器去完成,每个层次的类加载器都是如此,全部加载器的加载请求最终都应该传送至最顶层的类加载器中(扩展类加载器),只有当上级类加载器反馈本身没法完成这个加载请求(它的类加载范围中没有找到所需的类)时,下级类加载器才会去尝试本身加载这个类,这即是类加载器的双亲委托接待(Parents Delegation Model)虚拟机

 

双亲委托使得类加载器有了优先级顺序,保证了全部JVM须要的基础类如Obejct等都是使用的rt.jar的系统类,防止了用户自定义的同名类,形成类混乱

相关文章
相关标签/搜索