java热点代码 java热点代码分析( 三 )


下面简要说下Javac编译(前端编译)的过程 。
词法、语法分析
词法分析是将源代码的字符流转变为标记(Token)集合 。单个字符是程序编写过程中的的最小元素,而标记则是编译过程的最小元素 , 关键字、变量名、字面量、运算符等都可以成为标记,比如整型标志int由三个字符构成,但是它只是一个标记,不可拆分 。
语法分析是根据Token序列来构造抽象语法树的过程 。抽象语法树是一种用来描述程序代码语法结构的树形表示方式,语法树的每一个节点都代表着程序代码中的一个语法结构,如bao、类型、修饰符、运算符等 。经过这个步骤后,编译器就基本不会再对源码文件进行操作了,后续的操作都建立在抽象语法树之上 。
填充符号表
完成了语法分析和词法分析之后,下一步就是填充符号表的过程 。符号表是由一组符号地址和符号信息构成的表格 。符号表中所登记的信息在编译的不同阶段都要用到,在语义分析(后面的步骤)中,符号表所登记的内容将用于语义检查和产生中间代码,在目标代码生成阶段 , 党对符号名进行地址分配时,符号表是地址分配的依据 。
语义分析
语法树能表示一个结构正确的源程序的抽象,但无法保证源程序是符合逻辑的 。而语义分析的主要任务是读结构上正确的源程序进行上下文有关性质的审查 。语义分析过程分为标注检查和数据及控制流分析两个步骤:
标注检查步骤检查的内容包括诸如变量使用前是否已被声明、变量和赋值之间的数据类型是否匹配等 。
数据及控制流分析是对程序上下文逻辑更进一步的验证,它可以检查出诸如程序局部变量在使用前是否有赋值、方法的每条路径是否都有返回值、是否所有的受查异常都被正确处理了等问题 。
字节码生成
字节码生成是Javac编译过程的最后一个阶段 。字节码生成阶段不仅仅是把前面各个步骤所生成的信息转化成字节码写到磁盘中,编译器还进行了少量的代码添加和转换工作 。实例构造器init()方法和类构造器clinit()方法就是在这个阶段添加到语法树之中的(这里的实例构造器并不是指默认的构造函数,而是指我们自己重载的构造函数 , 如果用户代码中没有提供任何构造函数 , 那编译器会自动添加一个没有参数、访问权限与当前类一致的默认构造函数 , 这个工作在填充符号表阶段就已经完成了) 。
JIT编译
Java程序最初是仅仅通过解释器解释执行的,即对字节码逐条解释执行,这种方式的执行速度相对会比较慢 , 尤其当某个方法或代码块运行的特别频繁时 , 这种方式的执行效率就显得很低 。于是后来在虚拟机中引入了JIT编译器(即时编译器) , 当虚拟机发现某个方法或代码块运行特别频繁时,就会把这些代码认定为“Hot Spot Code”(热点代码) , 为了提高热点代码的执行效率 , 在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各层次的优化 , 完成这项任务的正是JIT编译器 。
现在主流的商用虚拟机(如Sun HotSpot、IBM J9)中几乎都同时包含解释器和编译器(三大商用虚拟机之一的JRockit是个例外,它内部没有解释器,因此会有启动相应时间长之类的缺点 , 但它主要是面向服务端的应用,这类应用一般不会重点关注启动时间) 。二者各有优势:当程序需要迅速启动和执行时 , 解释器可以首先发挥作用,省去编译的时间,立即执行;当程序运行后,随着时间的推移,编译器逐渐会返回作用,把越来越多的代码编译成本地代码后,可以获取更高的执行效率 。解释执行可以节约内存 , 而编译执行可以提升效率 。

推荐阅读