jvm类加载
当JVM运行过程中,用户需要加载某些类时,会按照下面的步骤(父类委托机制):
1 用户自己的类加载器,把加载请求传给父加载器,父加载器再传给其父加载器,一直到加载器树的顶层(bootstrap)。
2 父类加载器先针对其特定的位置加载,如果加载不到就转交给子类。
3 如果一直到最底层的加载器都没有加载到,那么就会抛出异常ClassNotFoundException。
因此,按照这个过程可以想到,如果同样在CLASSPATH指定的目录中和自己工作目录中存放相同的class,会优先加载CLASSPATH目录中的文件
类加载时机【lazy load】
预先加载
- Java基础类的加载:启动程序到jdk目录下找到并载入jvm.dll启动虚拟机初始化参数创建BootStrap Loader对象。BootStrap Loader对象称为启动类装载器,它会在虚拟机启动时一次性加载JJVM的基础类。
- 含main函数的类加载:BootStrap Loader另一项工作就是负责装载定义在sun.misc命名空间下的Launcher类。Launcher类有两个内部类,ExcClassLoader和AppClassLoader,其中,ExtClassLoader的父加载器被设置为null,表示它的父加载器为BootStarp Loader,即它由BootStrap Loader直接装载,而AppClassLoader的父加载器为ExtClassLoader,含有main函数入口的类由AppClassLoader在程序启动时加载。
按需加载
即运行时动态装载,当需要使用这个类时,JVM才会去动态装载它。
装载条件
当一个类的静态成员被第一次引用时,JVM就会去装载它,包括【静态方法-静态属性-构造方法】
需要特别注意的是:
- 当访问静态常量属性时,JVM加载类不会进行类的初始化工作。
- 虽然构造方法没有被显式地声明为静态方法,但它仍是类的静态成员特例,因此,当使用new关键字来构造对象时,会被当成类静态成员的引用,从而触发JVM装载该类。
按需装载流程
当需要使用某个类时,JVM首先会去检查该类的Class对象是否存在已经加载,如果没有,则执行以下步骤。
- 加载:查找并导入类的字节码,根据这些字节码创建Class对象
- 链接:其中分为三步
- 校验:检查导入的字节码的完整性,正确性、安全性。
- 准备:为静态域分配存储空间
- 解析:将符号引用转折为直接引用(非必需)
- 初始化
tomcat类加载
- bootstrap(等于jvm中的bootstrap+ext)
- system(catalina.bat指定类)
- webapp(WEB-INF/classes、WEB-INF/lib)
- common(CATALINA_HOME/lib)