diff --git a/blogs/Java/口水话/JVM 相关口水话.md b/blogs/Java/口水话/JVM 相关口水话.md index 077ca55..a9bf059 100644 --- a/blogs/Java/口水话/JVM 相关口水话.md +++ b/blogs/Java/口水话/JVM 相关口水话.md @@ -138,3 +138,10 @@ ZGC 作为新一代的垃圾回收器,在设计之初就定义了三大目标 #### 编译器优化 +在公司内部,我是分享过一次关于编译优化的相关知识。课题是 “从 final '能够' 提升性能,谈编译优化”。 + +对于 Java 代码的编译,分为前端编译和后端编译。前端编译是指通过 javac 工具,将 Java 代码转化为字节码的过程。既然 javac 负责字节码的生成,那肯定就会有一些通用的优化手段。比如常量折叠、自动装拆箱、条件编译等,其次还有 JDK9 使用 StringContactFactory 对 "+" 的重载提供的统一入口等。后端编译则指 JVM 内置的解释器和即时编译器(C1、C2)。JVM 在对代码执行的优化可以分为运行时优化和即时编译器(JIT)优化。运行时优化主要是解释执行和动态编译通用的一些机制,比如说锁机制(如偏斜锁)、内存分配机制(如 TLAB)等。除此之外,还有一些专门用于优化解释执行效率的,比如说模版解释器、内联缓存(inline cache,用于优化虚方法调用的动态绑定)。JVM 的即时编译器优化是指将热点代码以方法为单位转化成机器码,直接运行在底层硬件之上。它采用了多种优化方式,包括静态编译器可以使用的如方法内联、逃逸分析,也包括基于程序的运行 profile 的投机性优化。 + +下面我就主要讲一下方法内联和逃逸分析。 + +方法内联,它指的是在编译的过程中遇到方法调用时,将目标方法的方法体纳入编译范围之中,并取代原方法调用的优化手段。方法内联不仅可以消除调用本身带来的性能开销,还可以进一步触发更多的优化。因此,它可以算是编译优化里最为重要的一环。以 getter/setter 为例,如果没有方法内联,在调用 getter/setter 时,程序需要保存当前方法的执行位置,创建并压入用于 getter/setter 的栈桢、访问字段、弹出栈桢,最后再恢复当前方法的执行。而当内联了对 getter/setter 的方法调用后,上述操作就只剩下字段访问了。 \ No newline at end of file