jvm-类加载


一.加载

1.根据类的全限定名获取类的二进制数据流 2.解析类的二进制数据流在方法区生成动态的数据结构 3.在堆中生成对应的Class对象,作为方法区中的类数据的入口   数组类不是类加载器加载,而是由jvm在运行时根据需要加载。但是数组元素的类型是由类加载器加载。  

二.链接

1.验证 验证class文件是否符合java虚拟机规范 2.准备 为类的静态变量分配内存,对类属性进行默认初始化 final类型的属性,在编译期就会分配了,在准备阶段显式赋值 3.解析 符号引用转换为直接引用 符号引用:用一组符合描述引用对象:(类和接口的全限定名,方法和字段的名称和描述符) 直接引用:直接指向引用对象的地址或偏移量  

三.初始化

方法,对类中的属性进行显示赋值,只会执行一次,线程安全。 只有主动使用才会对类进行初始化操作 主动使用: 1.创建类实例:new ,反射,克隆,反序列化 2.调用类的静态方法 3.使用类的静态字段 4.使用反射类的方法 5.初始化子类 6.直接或间接实现接口的类的初始化,会导致接口的初始化 7.执行的主类(main方法所在的类) 8.初次调用MethodHandle实例,初始化MethodHandle指向的方法所在的类  

四.static final 属性

1.如果是基本数据类型,或string字面量在准备阶段显式赋值,否则在初始化阶段显式赋值。  

五.类的卸载

类的所有实例已经被回收 类的Class对象不再被引用 加载该类的加载器已经被回收   才允许被回收,不是一定。    

六.类加载器

1.分类: 启动类加载器 自定义类加载器(继承自classloader):扩展类加载器,应用程序类加载器   2.类加载器的命名空间 类加载器和类本身一同确认其在java虚拟机中的唯一性 每个类加载器都有自己的命名空间,由该加载器及所有的父加载器所加载的类组成   3.类加载机制的基本特征 ①双亲委派模型 当一个请求类加载器进行加载时,类加载器首先交给其父类加载器进行加载,一直向上委托,当父类加载器无法加载时,再由子类加载器进行加载   双亲委派模型的优势 保护核心类的安全,防止被篡改 避免类的重复加载 劣势 顶层的加载器无法访问底层的加载器所加载的类   破坏双亲委派机制 1.在jdk1.2之前,双亲委派模型还没有引入 2.线程上下文类加载器,默认是应用程序类加载器。spi机制,父类加载器请求子类加载器完成类加载的行为。 3.代码热替换,热部署 由于不同的classloader加载同一个类,在虚拟机内部,会认为这两个类完全不同。   ②可见性 子类加载器可以访问父类加载器加载的实现   ③单一性 由于父类加载对子类加载器可见,所以父类加载器加载过的类型,子加载器不会重复加载,但是类加载器邻居间,同一类型仍会加载多次。   4.自定义类的加载器 重写loadclass方法 重写findclass方法 1.读取字节码文件为字节数组 2.调用defineClass方法将字节数组的数据转换为Class实例   自定义类加载的用处 1.隔离加载类 2.修改类加载的方式 3.扩展加载源 4.防止源码泄露   5.jdk1.9新特性 ①扩展类加载器被移除,被重命名为平台类加载器 ②jdk 9的jar 进行了模块化的构建 ②类加载器的委派关系发生了变化 当收到类加载请求,在委派给父加载器加载前,要先判断该类是否能够归属到某一个系统模块,如果有归属关系,就要优先委派给负责的模块加载器进行加载