Java运行流程(以HotSpot为例)
编译阶段:
1. 编写代码保存为Java文件
2. 编译器(javac)将 .java 文件编译成 .class 文件,生成字节码
运行阶段:
通过解释器(Interpreter)进行解释执行;
通过JIT(即时编译器)将“热点代码(运行频繁的方法或者代码块)”编译成本地机器码
Java 是编译与解释共存的
编译器:一次性编译成机器码;
解释器:一句一句解释成机器码;
解释器和编译器两者各有优势:
当程序需要迅速启动和执行时,解释器剋首先发挥作用,省去编译时间,立即运行。当程序启动后,随着时间的推移,编译器逐渐发挥作用,越来越多的代码编译成本地机器码,这样可以减少解释器中间的损耗提高执行效率。
当程序运行环境中内存资源限制较大,可以使用解释执行节约内存,反之可以使用编译执行提高效率
AOT (Ahead of Time,提前编译) & JIT(Just in Time, 即时编译)
AOT(Ahead of Time),提前编译器直接将字节码编译成机器码,这样避免了 JIT 预热开销。
JIT(Just in Time), 编译器将“热点代码“在运行时完成第一次编译后,其会将字节码对应的机器码保存下来,下次可以直接使用,因此执行的次数越多,它的速度就越快。
AOT 可以提前编译节省启动时间,那为什么JIT仍是主流?
这和 Java 的动态特性有关系了。java动态代理中往往需要使用 ASM 技术,而这种技术原理大致是运行时直接在内存中生成并加载修改后的字节码,如果全部使用 AOT 提前编译,也就不能使用 ASM 技术了