思路:
写代码编译成字节码->使用字节码涉及类加载机制->类加载机制涉及类加载器->类加载器涉及双亲委派机制(概念和模型)->打破双亲委派机制
我们写好的代码通过编译工具编译成字节码被打成jar包或war包,然后通过JVM才能使用的。jvm通过类加载机制来做好使用前的所有数据准备。
类加载机制流程:加载 -> 验证 -> 准备 -> 解析 -> 初始化 -> 使用 -> 卸载
加载时机:代码中用到这个类的时候(将class文件加载到JVM中),涉及类加载器
验证、准备、解析(这三者细节复杂,没必要去了解)
验证:验证是否符合JVM规范(防止篡改)
准备:给加载的类和它的类变量分配内存空间,并且给了默认初始值
解析(静态解析):把某些符号引用转化为直接引用,(就是编译期间就能确定调用的版本,解析范围包括、字段、接口、方法即非虚方法,包括: 调用静态方法, 调用构造方法, 私有方法, 父类方法,final修饰的方法。直接引用就是指向类变量、对象或方法的指针)
初始化:执行赋值逻辑,准备阶段只是设置了初始值。这个是核心阶段,执行类的初始化。(实例化对象、含main()方法的主类,初始化一个类时先初始化其父类)
使用:程序间调用
卸载:即销毁对象,一般由垃圾回收器完成,代码层面的销毁只是将引用置为null;
类加载器:4类加载器
启动类加载器Bootstrap classLoader:负责加载我们在机器上安装的Java目录lib下的核心类的
扩展类加载器(Extension ClassLoader):负责加载我们在机器上安装的Java目录lib\ext下的拓展类
应用程序类加载器(Application ClassLoader):负责去加载“ClassPath”环境变量所指定的路径中的类,即你写的那些类
自定义类加载器:去根据你自己的需求加载你的类
双亲委派机制:
JVM的类加载器是有亲子层级结构的,就是说启动类加载器是最上层的,扩展类加载器在第二层,第三层是应用程序类加载器,最后一层是自定义类加载器。
概念:就是假设你的应用程序类加载器需要加载一个类,他首先会委派给自己的父类加载器去加载,最终传导到顶层的类加载器去加载。但是如果父类加载器在自己负责加载的范围内,没找到这个类,那么就会下推加载权利给自己的子类加载器。目的:可以避免多层级的加载器结构重复加载某些类。
如何打破双亲委派机制:继承ClassLoader后重写loadClass方法。
保持双亲委派机制:继承ClassLoader后重写findClass方法。
参考<<深入理解java虚拟机>> P272