Java代码执行机制
一、java源码编译机制
一个java文件编译为.class文件的流程图。
Parse an Enter阶段:
Parse:将代码字符串转换为token序列(com.sun.tools.javac.parser.Scanner),再将token转换为语法抽象树(com.sun.tools.javac.parser.Parser)
Enter:将符号输入到符号表.内容包括确定超类型和接口,添加类默认构造器
Annotation阶段:
主要处理用户自定义的注解
Analyse and Generate阶段:
Analyse:将语法抽象树进行一系列分析,包括:检查变量使用前是否声明,检查类型匹配,有返回值的方法必须有返回值等等
Generate:生成.class文件(com.sun.tools.javac.jvm.Gen)
生成的class文件包括:
结构信息:class文件格式版本号及各部分数量,大小
元数据:类,父类,接口信息,方法声明,常量池
方法信息:对应java源码中语句、表达式部分
二、类加载机制
1.Load(装载):
找到二进制字节码并加载到JVM中
2.Link(链接):
VerifyàPrepareàResolve
校验阶段:
校验二进制字节码格式,初始化装载类中的静态变量及解析类中调用的接口、类
如果格式不符合,会抛出VerifyError异常;校验过程中碰到要引用其他的接口和类,也要进行加载;如果加载失败,抛出NoClassDefFoundError一样
Prepare准备阶段
完成校验后,JVM初始化类中的静态变量,并赋予默认值
最后,对类中的所有属性、方法进行验证,保证对应的属性、方法存在,否则抛出NoSuchMethodError、NoSuchFiledError
3.Intialize(初始化):
要想初始化,必须通过校验及准备阶段
初始化就是执行类的static初始化代码、构造器代码、static属性的初始化。初始化被触发的几种情况:
|-调用new
|-反射调用类中的方法
|-之类调用了初始化
|-JVM启动过程中指定的初始化类
ClassLoader方面的常见异常
ClassNotFoundException:
很常见的异常,加载的类不在Classpath中就会抛出此异常。对于自定义的类加载器(继承ClassLoader),需要查看这个ClassLoader加载类的过程来分析类的加载路径
NoClassDefFoundError:
public class A{ public B b = new B(); } |
类A引用类B,若B不存在或ClassLoader没法加载B,则抛出此异常
3.LinkageError
重复加载类造成的异常,自定义ClassLoader情况下容易出现,因为此类已经在ClassLoader加载过了
4.ClassCastException
类型转换异常,较容易查找,比较难的是两个类A对象被不同的ClassLoader加载所引发的异常