1 类加载子系统:
作用:
类加载子系统负责从文件系统或者加载class文件.只负责加载类,由执行引擎执行,存放在方法区(元空间).
2 类加载的角色:
1.class file 存在于硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载 JVM 当中来,根据这个模板实例化出 n 个一模一样的实例.
2.class file 加载到 JVM 中,被称为 DNA 元数据模板,放在方法区中.
3.在.class–>JVM–>最终称为元数据模板,此过程就要有一个运输工具(类加 载器 Class Loader),扮演一个快递员的角色.负责运输
3.类加载的过程
一.加载:(根据类的地址从硬盘上读取类的信息,将信息读入到方法区,生成Class类的对象)
1.通过类名(地址)获取此类的二进制字节流. (读取文件)
2.将这个字节流所代表的静态存储结构转换为方法区(元空间)的运行时结构.
3.在内存中生成一个代表这个类的 java.lang.Class 对象,作为这个类的各种数据的访问入口.
二.链接:
1.验证:检验被加载的类是否有正确的内部结构,并和其他类协调一致;(通俗来说就是验证字节码文件是否当前虚拟机所支持的文件格式,语法格式)
验证文件格式是否一致: class 文件在文件开头有特定的文件标识(字节码文件都以 CA FE BA BE 标识开头);主,次版本号是否在当前 java 虚拟机接收范围内.
元数据验证:对字节码描述的信息进行语义分析,以保证其描述的信息符合 java 语言规范的要求,例如这个类是否有父类;是否继承浏览不允许被继承的类 (final 修饰的类)…
2.准备:准备阶段则负责为类的静态属性(静态的随着类的加载而加载)分配内存,并设置默认初始值; 不包含用 final 修饰的 static 常量,在编译时进行初始化.(为静态成员分配默认值(int 默认值为0),static final 在编译期间赋值)
例如:
pubic static int val = 123;
val在准备阶段后的初始值是0;而不是123;
但是 pubic static final int val = 123;
val在准备阶段的值就是123;
3.解析:将类的二进制数据中的符号引用替换成直接引用(符号引用是 Class 文件的逻辑符号,直接引用指向的方法区中某一个地址).
例如:
编写代码时: 方法1 中调用 方法2 (符号引用)
类加载到内存后: 把符号引用地址 换成 内存的地址引用
三.初始化:
1.类什么时候初始化?
1 )创建类的实例,也就是 new 一个对象
2)访问某个类或接口的静态变量,或者对该静态变量赋值
3)调用类的静态方法
4)反射(Class.forName(“”))
5)初始化一个类的子类(会首先初始化子类的父类)
2.类的初始化顺序 :
对 static 修饰的变量或语句块进行赋值.
如果同时包含多个静态变量和静态代码块,则按照自上而下的顺序依次执行。
如果初始化一个类的时候,其父类尚未初始化,则优先初始化其父类。
顺序是:父类 static –> 子类 static –> 父类构造方法- -> 子类构造方法
(先初始化静态的,多个静态的按照从上向下的顺序执行,
如果类有父类,先初始化父类的静态,然后子类,
如果是创建对象,先调用父类的构造方法,然后是子类自己的构造方法.)