《深入理解Java虚拟机》读书笔记之程序编译与代码优化

本文详细探讨了Java代码的编译过程,包括前端编译(Javac)、JIT编译和AOT编译。讲解了词法、语法分析,符号表填充,注解处理,语义分析和字节码生成等步骤。此外,还介绍了Java的语法糖如泛型、自动装箱拆箱、Foreach循环和变长参数的实现。同时,阐述了热点代码识别和JIT编译优化技术,如方法内联、冗余消除和逃逸分析等。
摘要由CSDN通过智能技术生成

从计算机程序出现的第一天起,对效率的追求就是程序天生的坚定信仰,这个过程犹如一场没有终点、永不停歇的F1方程式竞赛,程序员是车手,技术平台则是在赛道上飞驰的赛车。

  1. Java代码的三种编译过程
    1. 前端编译:将*.java文件转变为 *.class文件,如Javac
    2. JIT编译:将*.class文件转变为转变为机器码,如HotSpot的C1,C2编译器
    3. AOT编译:直接把*.java文件编译为本地机器代码,如GCJ编译器
  2. Javac的编译过程(深入学习可以去读Javac的源码)
    在这里插入图片描述
    1. 解析和填充符号表
      1. 词法、语法分析:词法分析是将源码字符流转变为Token集合,Token是编译过程的最小元素如关键字,变量名,字面量,运算符等;语法分析是根据Token集合来构造抽象语法树。(这里涉及编译原理的知识)
      2. 填充符号表:符号表在后续处理分析过程中需要使用,类似于key,value的结构。
    2. 注解处理:源代码中写的注解就在此时进行处理,通过插入式注解处理器API对源代码里的注解进行处理,可能会对抽象语法树进行修改,如果修改了,就要重新进行一次解析和填充符号表,这个过程称为一个round,直到没有对抽象语法树有修改才进入下一阶段。
    3. 语义分析和字节码生成
      1. 标注检查:检查赋值和变量类型是否匹配,此时有一个重要的动作,常量折叠。
      2. 数据及控制流分析:分析代码的基本语法逻辑是否合法,对于局部变量final修饰的保证就是在此时检测的,运行时不会检测
      3. 解语法糖:Java里的语法糖需要在此时替换为实际的代码实现,因为虚拟机是不认语法糖的
      4. 字节码生成:这部分主要是将前面生成的语法树,符号表写入磁盘,增加默认构造函数是在此阶段完成的。
  3. Java常见语法糖
    1. 擦除式泛型:Java的泛型符只存在于源码,编译之后的字节码被插入了强制类型转换。但是擦除,仅仅是对Code属性中的字节码进行了擦除,元数据还是有保留泛型信息,这也是为什么能通过反射取得参数化类型的根本依据。
    2. 自动装箱,拆箱:用valueOf函数和intValue函数实现
    3. Foreach循环:使用迭代器实现,所以要求被遍历的类必须要实现Iterable接口。
    4. 变长参数:用数组实现
  4. 热点代码有哪些
    1. 被多次调用的方法体
    2. 被多次执行的循环体(JIT编译的仍然是这个循环的整个方法体,而不是这个循环)
  5. 如何判定一个代码是热点代码
    1. 基于采样的热点探测:周期性的检查线程栈顶,发现一个方法出现的频率很高就认为是热点代码
    2. 基于计数器的热点探测:为代码块建立一个计数器,当计数值突破阈值的时候就认为是热点代码,触发JIT编译。主要有两种计数器分别是方法调用计数器和回边计数器。方法调用计数器存在热度衰减。
  6. JIT编译优化技术
    1. 方法内联
    2. 冗余消除访问
    3. 复写传播
    4. 无用代码消除
    5. 公共子表达式消除
    6. 数组边界检查消除:采用提前到编译器检查或者隐式异常处理(会进入内核态)实现
    7. 逃逸分析:栈上分配,同步消除,标量替换等

这部分主要讲了Java代码如何从*.java文件一步步编译称为*.class文件,不同的编译方式下进行的优化,以及不同的执行方式。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值