前期编译
java源代码——>JVM字节码(class文件)
大致的编译过程:
解析与填充符号表——>注解处理——>分析与字节码生成
具体就是词法分析、语法分析、构建语法树等过程,此阶段几乎不会对代码做出优化,撑死就是做一些冗余处理,比如 int a = 3 + 1; 改成 int a = 4;等。
值得一说的是解语法糖的过程,java有大量的语法糖,泛型、自动装/拆箱、变长参数、foreach循环等。
有语法糖不一定代表性能的提升,大多时候可能都是为了方便开发人员,极端的说它可以有也可以没有。同时,小心语法糖陷阱,比如自动装箱(不要期待在任何时候都会帮你包装成类)。
后期编译
字节码——>机器码(对应平台的)
可以把此阶段的编译器与C++编译器相比较因为功能类似。
解释器与编译器,前者可以直接运行,解释一句就运行一句,因此效率不高;后者先将运行代码编译成机器码才运行,需要等待编译的时间,但运行快。
C++编译器:静态的,把源代码全部编译成机器码再运行,编译和运行分的很开。
JIT(JVM内置):即时编译器,用到什么就编译什么,编译和运行是交叉的。一般有一个解释器和一个编译器配合执行。
JAVA的代码优化大都集中在JIT里,优化算法之多让人目眩,循环展开、方法内链,常量重叠等等。
PS:一个小小的关注点,局部变量没有访问标志,虽然可以这么写:
final int a = 0;
但这个final是没有意义的,也不是说没有意义,就是说在class文件中没有任何体现,final的意义仅仅在前期编译中被保证。如果反射能修改方法体的话,那这个就有意思了(事实上,反射不能修改方法体=。=)
时间: 2024-11-08 17:26:31