类加载的双亲机制:
class加载到JVM中有三个步骤
装载:(loading)找到class对应的字节码文件。
连接:(linking)将对应的字节码文件读入到JVM中。
初始化:(initializing)对class做相应的初始化动作。
1:虚拟机启动时,需要指定一个执行的主类(包含main方法的类),虚拟机会先初始化这类
2:是什么时候要加载类:
1、使用new关键字实例化对象、读取或设置一个类的静态字段(被final修饰、已在编译期把结果放入到常量池的静态字段除外),以及调用一个类的静态方法的时候。
2、使用java.lang.reflect包的方法对类进行反射调用时,如果此类没有初始化,则要触发其初始化。
3、当初始化一个类时,发现其父类还没有进行初始化,则需要先触发其父类的类的初始化
4、当虚拟机启动时,用户需要指定一个要运行的主类(包括main方法的那个类),虚拟机会先初始化这个主类。
5、JDK1.7新增:如果一个java.lang.invoke.MethodHandle实例最后的解析结果是REF_getStatic、REF_putStatic、REF_invokeStatic的方法句柄,并且这个方法的句柄所对应的类没有进行过初始化,则需要先触发其初始化。
类加载器分类
在虚拟机的角度上,只存在两种不同的类加载器:
启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;
其它所有的类加载器,这些类加载器都由Java语言实现,独立于虚拟机外部,并且全部继承自java.lang.ClassLoader,
双亲委派模型是指:
如果一个类收到了类加载的请求,不会自己先尝试加载,先找父类加载器去
完成。当顶层启动类加载器表示无法加载这个类的时候,子类才会尝试自己
去加载。当回到最开的发起者加载器还无法加载时,并不会向下找,而是抛
出ClassNotFound异常。(如果类A中引用了类B,Java虚拟机将使用加
载类A的类加载器来加载类B)
BootStrap ClassLoader:主要加载%JRE_HOME%\lib下的rt.jar(顶级加载器C++)
Extention ClassLoader:主要加载目录%JRE_HOME%\lib\ext目录下的jar包和class文件
AppClassLoader:主要加载当前应用下的classpath路径下的类
例如:当jvm要加载Test.class的时候,
(1)首先会到自定义加载器中查找,看是否已经加载过,如果已经加载过,则返回字节码。
(2)如果自定义加载器没有加载过,则询问上一层加载器(即AppClassLoader)是否已经加载过Test.class。
(3)如果没有加载过,则询问上一层加载器(ExtClassLoader)是否已经加载过。
(4)如果没有加载过,则继续询问上一层加载(BoopStrap ClassLoader)是否已经加载过。
(5)如果BoopStrap ClassLoader依然没有加载过,则到自己指定类加载路径下("sun.boot.class.path")查看是否有Test.class字节码,有则返回,没有通
知下一层加载器ExtClassLoader到自己指定的类加载路径下(java.ext.dirs)查看。
(6)依次类推,最后到自定义类加载器指定的路径还没有找到Test.class字节码,则抛出异常ClassNotFoundException