类从加载到虚拟机内存开始,到卸载出内存,它的整个生命周期包括:加载(loading)、验证(verification)、准备(preparation)、解析(resolution)、初始化(initialization)、使用(using)、卸载(unloading)7个阶段。其中验证、准备、解析3个部分统称为链接(linking)java
JVM规范规定有且仅有下面5种状况会触发类的初始化(加载、验证、准备在这以前完成):spa
- 遇到new、getstatic、putstatic、invokestatic这4个字节码命令时,若是累没有进行过初始化,则须要先触发其初始化。这4条命令对应的场景:使用new关键字实例化对象、读取或设置一个类的静态变量(被final修饰、已在编译期把结果放入常量池的除外),以及调用静态方法的时候。
- 使用java.lang.reflect包的方法对类进行反射调用的时候,若是类没有加载过
- 当初始化一个类当其父类没有初始化过,则先初始化父类
- 当虚拟机启动,会先初始化main方法主类
- 当使用JDK 7的动态语言支持时,若是一个java.lang.invoke.MethodHandle实例最后解析结果REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,而且这个方法句柄所对应的类没有进行过初始化,则须要先触发其初始化
接口的初始化与类初始化相似,只有3.不一样,父类接口只在用到时候才会初始化设计
ClassLoader类加载器,主要的做用对象
- 负责将Class加载到JVM中;
- 审查每一个类应该由谁加载;
- 将Class字节码从新解析成JVM统一要求的对象格式;
ClassLoader的几个主要方法:继承
- defineClass(byte[], int, int)用来将byte字节流解析成JVM可以识别的Class对象
- resolveClass(Class<?>)用来链接(Link)类
- findClass(String)用来实现类的加载规则,从而取得加载类的字节码。而后能够结合defineClass方法生成类的Class对象,若是想在类被加载到JVM中时就被链接,能够接着调用resolve方法。
- loadClass(String)中会调用findClass方法,默认不调用resolve方法,能够同太重载方法loadClass(String,boolean)在类加载到JVM是被连接,否则将在对象真正实力化时才进行连接
ClassLoader是一个抽象类,它有不少子类,咱们若是要实现本身的ClassLoader,通常都会继承URLClassLoader这个子类,由于这个类已经帮咱们实现了大部分工做。接口
整个JVM中提供了三个ClassLoader类,这三个ClassLoader能够分为两种类型,加载JVM自身工做须要类的加载器和为其余类服务的加载器:生命周期
- Bootstrap ClassLoader,这个ClassLoader主要加载JVM自身工做须要的类,这个ClassLoader彻底是JVM本身控制,因此不遵照双亲委托接待(Parents Delegation Model)规则。将%JAVA_HOME%\lib路径下或-Xbootclasspath参数指定路径下的、能被虚拟机识别的类库(仅按照文件名识别,如:rt.jar,名字不符合的类库不会被加载)加载至虚拟机内存中
- ExtClassLoader,用来加载System.getProperty("java.ext.dirs")目录下的类,(默认值是%JAVA_HOME%\jre\lib\ext,可由VM参数-Djava.ext.dirs指定)
- 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的系统类,防止了用户自定义的同名类,形成类混乱