从Java源码编译开始说起
分为三个步骤:
1:分析和输入到符号表
分析:词法和语法分析,将代码字符串转变为token序列,由token序列生产抽象语法树
输入:将符号输入到符号表,确定类的超类型和接口,添加默认构造器,将类中出现的符号输入到自身的符号表中
2:注解处理
处理用户自定义的annotation,可以自动生成代码或者进行一些特殊检查
3:语义分析和生产class文件
基于之前的抽象语法树进行语义分析
将一些名字、表达式和变量、方法这些联系到一起;检查语句可达,检查语法检查变量
之后开始生成class文件,步骤为:
1:先执行初始化块或声明属性时制定的初始值,再执行构造器里制定的初始值。
1:将静态成员初始化器收集为()
2:将抽象语法树生成字节码,后序遍历
3:从符号表生成class文件
4:class文件中的其他东西
1:结构信息
2:元数据:源码中声明和常量的信息
3:方法信息:源码中语句与表达式的信息
综上所述:class文件是个完整的子描述文件,字节码在其中只占了很小的部分
JVM通过类加载来装载class文件
分为三个步骤:
1:装载
JVM通过类的全限定名和类加载器完成类的加载
1:通过类的全限定名找到二进制字节流
2:把其中与方法区有关的东西变成方法区的运行时数据结构
3:在堆中生成这个类的访问入口
如果是数组,数组型类中的元素类型由所在的ClassLoader负责加载,数组类由JVM直接创建
2:链接
1:对二进制字节码的格式进行校验
2:初始化类中的静态变量,赋默认值
3:解析类中调用的接口、类,确保其调用的属性、方法存在
3:初始化
在执行初始化过程之前,首先必须完成链接过程中的校验和准备阶段,解析阶段则不强制
初始化就是执行类中的静态初始化代码、构造器代码及静态属性的初始化
四种情况初始化会被触发:
1:调用了new
2:反射调用类中方法
3:子类调用初始化
4:JVM启动过程中指定的初始化类
类加载要通过ClassLoader及其子类
Bootstrap ClassLoaderL:并非ClassLoader的子类,代码中无法获取,Sun JDK启动时会初始化这个类
Extension ClassLoader: