1.类加载:类加载器将class文件加载到虚拟机的内存
加载:在硬盘上查找并经过IO读入字节码文件
链接:执行校验、准备、解析步骤
校验:校验字节码文件的正确性
准备:给类的静态变量分配内存,并赋予默认值
解析:类装载器装入类所引用的其余全部类
初始化:对类的静态变量初始化为指定的值,执行静态代码块java
2.类加载器:spring
启动类加载器(BootstrapClassLoader):负责加载JRE的核心类库,如jre目标下的rt.jar,charsets.jar等
扩展类加载器(ExtensionClassLoader):负责加载JRE扩展目录ext中JAR类包
系统类加载器(ApplicationClassLoader):负责加载ClassPath路径下的类包
用户自定义加载器(CustomClassLoader):负责加载用户自定义路径下的类包jvm
执行以下代码,查看对应的类加载器:ide
package com.nijunyang.spring; import com.sun.crypto.provider.BlowfishCipher; /** * @author: create by nijunyang * @date:2019/6/16 */ public class ClassLoaderTest { public static void main(String[] args) { System.out.println(String.class.getClassLoader()); System.out.println(BlowfishCipher.class.getClassLoader().getClass().getName()); System.out.println(ClassLoaderTest.class.getClassLoader().getClass().getName()); System.out.println(ClassLoader.getSystemClassLoader().getClass().getName()); } }
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------spa
能够看到String的类加载器null,由于String是在java核心包rt.jar里面这里面东西是由启动类加载器加载的,而启动类加载器是由C/C++实现的,根本不在JDK里面。
BlowfishCipher的类加载器是ExtClassLoader,而这个类正是Jre扩展目录ext中jar包所在的类
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3.类加载机制--全盘委托和双亲委派机制3d
全盘委托:当一个ClassLoader加载一个类时,除非显示的使用另外一个ClassLoader,该类所依赖和引用的类也由这个ClassLoader载入,好比说A依赖B,那么B的加载器和A的加载器同样。对象
双亲委派:指先委托父类加载器寻找目标类,在找不到的状况下在本身的路径中查找并载入目标类,感受说父类加载器不是很合适,由于没有这一层关系,感受更像是上下级关系。委托上级加载器寻找目标类。blog
双亲委派的好处:ip
1.避免类重复加载,上级加载了,下级就不须要再加载内存
2.由于核心API都有固定的加载器,能够防止核心库被篡改: 自定义一个String类,一样在java.lang包下,运行代码会发现启动报错,实际加载的java.lang.String类并无main方法,说明实际加载的String类并非咱们自定义的String类,而是由于双亲委派机制,往上委托到启动类加载器,去加载rt.jar里面的String类
4.类加载过程
实际上jvm对class文件是按需加载的,须要的时候才加载(运行时动态加载),并不是一次所有加载进去,jvm启动参数加上:-verbose:class 查看类加载
package com.nijunyang.spring; /** * @author: create by nijunyang * @date:2019/6/16 */ public class ClassLoaderTest { static { System.out.println("静态块执行"); } public static void main(String[] args) throws InterruptedException { Thread.sleep(3000); System.out.println(System.currentTimeMillis()); new A(); System.out.println("A对象建立完毕"); new B(); } }
从结果中咱们能够看到
1.从本地/E:/IdeaProject/tuling/spring/target/classes/下面去加载当前运行类ClassLoaderTest.class文件
2.初始化类,执行静态代码块
3.main方法运行,睡了5s以后打印当前时间,当咱们new A的时候才去本地加载A.class文件到内存,再实例化A
4.A建立完毕以后,再去加载B.class,完成B的初始化