JVM 虚拟机之编译优化(下)

简介: JVM 虚拟机之编译优化

同步消除(Synchronization Elimination


线程同步本身是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那么这个变量的读写肯定就不会有竞争, 对这个变量实施的同步措施也就可以安全地消除掉。


VM 参数:


-XX:+EliminateLocks       开启锁消除(JDK1.8 默认开启)


公共子表达式消除(Common Subexpression Elimination)


公共子表达式消除是一个非常经典的、普片应用各种编译器的优化技术。


在同一个作用域下,如果程序中有公共的计算表达式,多次出现参与运算的结果相同,计算结果为 E,那么后面的表达式直接用 E 替代结果。


一个表达式已经被计算过了,并且从先前计算到现在的计算所有的变量值都没有发生变化,称为 E 为公共表达式。对于这种表达式,我们就不需要重新计算了,只需要使用之前计算过的表达式结果替代 E 。如果这种代码优化局限与程序代码块内,可称为局部公共表达式消除(Local Common Subexpression Elimination)。如果这种优化的范围覆盖了多个代码块,那就称为全局公共子表达式消除(Global Common Subexpression Elimination)。


举个例子:


int d = (c * b) * 12 + a + (a + c * b);


虚拟机的即时编译器会进行代码优化(因为在代码块内 c、b 的之没有改变,编译器认为没必要多次计算),上面的表达式会被优化为:


int d = E * 12 + a + (a + E);


在这个时候编译器也可能会进行代数简化(Algebraic Simplification)。


int d = E * 13 + a + a


经过简化后再计算起来就可以节省一些 CPU 的时间。


数组边界检查消除(Array Boounds Checking Elimination)


数组边界检查消除(Array Boounds Checking Elimination)是及时编译器优化的经典技术。对于 Java 而言本来就是一门动态安全的语言,比如我们访问一个数组 foo[i] 的时候:


  1. 先去检查数组是否为空,如果 foo 为空返回 NullPointException异常。


  1. 如果数组越界会得到 ArrayIndexOutOfBoundsExecption异常。


其实 JVM 为我们做了非常多的隐含条件判断。


但是对于这些操作,为了安全肯定是要做的,但是如果对 foo[i] 循环取值,如果编译器通过分析发现可以判定循环变量的取值永远在区间 [0, foo.length] 之内,那么在这个循环中我们就可以吧这个那个数组的上下界限检查消除掉。


举个例子:


if (i >= 0 && i < foo.length) {
    return foo[i];
}


优化过后:


return foo[i];


除此之外还有一种隐式异常处理,Java 空指针检查和算数运算除数为 0 的检查都采用了这种方案。 举个例子:


if (foo != null) {
    return foo.value;
} else {
    throw new NullPointException();
}


在隐式异常优化之后:


try {
    return foo.value
} catch (segment_fault) {
    uncommon_trap();
}


虚拟机会注册一个  Segment Fault 的信号异常处理器,当 foo 不为空的时候,访问 value 是没有任何开销的。但是如果 foo  为空,会进入异常处理涉及到进程从用户态转到内核态的处理,处理完成后又回到用户态,同样一次操作比判空检查慢的多。

HptSpot 会更具运行期收集到的监控信息自动选择最优方案。


其他优化:自动装箱消除(Autobox Elimination)、安全点消除 (Safepoint Elimination)、消除反射(Dereflection)等。


参考文档


  • 《深入理解 JVM 虚拟机》周志明


相关文章
|
7天前
|
监控 Java 调度
探秘Java虚拟机(JVM)性能调优:技术要点与实战策略
【6月更文挑战第30天】**探索JVM性能调优:**关注堆内存配置(Xms, Xmx, XX:NewRatio, XX:SurvivorRatio),选择适合的垃圾收集器(如Parallel, CMS, G1),利用jstat, jmap等工具诊断,解决Full GC问题,实战中结合MAT分析内存泄露。调优是平衡内存占用、延迟和吞吐量的艺术,借助VisualVM等工具提升系统在高负载下的稳定性与效率。
24 1
|
3天前
|
存储 监控 安全
深入理解Java虚拟机(JVM)原理
深入理解Java虚拟机(JVM)原理
|
9天前
|
Java 编译器
Java健壮性 Java可移植性 JDK, JRE, JVM三者关系 Java的加载与执行原理 javac编译与JAVA_HOME环境变量介绍 Java中的注释与缩进 main方法的args参数
Java健壮性 Java可移植性 JDK, JRE, JVM三者关系 Java的加载与执行原理 javac编译与JAVA_HOME环境变量介绍 Java中的注释与缩进 main方法的args参数
10 1
|
13天前
|
存储 Java C++
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据
Java虚拟机(JVM)管理内存划分为多个区域:程序计数器记录线程执行位置;虚拟机栈存储线程私有数据,如局部变量和操作数;本地方法栈支持native方法;堆存放所有线程的对象实例,由垃圾回收管理;方法区(在Java 8后变为元空间)存储类信息和常量;运行时常量池是方法区一部分,保存符号引用和常量;直接内存非JVM规范定义,手动管理,通过Buffer类使用。Java 8后,永久代被元空间取代,G1成为默认GC。
23 2
|
2天前
|
存储 监控 安全
深入理解Java虚拟机(JVM)原理
深入理解Java虚拟机(JVM)原理
|
9天前
|
存储 监控 算法
深入理解Java虚拟机(JVM)原理与调优技巧
深入理解Java虚拟机(JVM)原理与调优技巧
|
10天前
|
存储 缓存 Java
JVM的即时编译(JIT)优化原理:加速程序的执行
JVM的即时编译(JIT)优化原理:加速程序的执行
|
10天前
|
Java UED 开发者
JVM逃逸分析原理解析:优化Java程序性能和内存利用效率
JVM逃逸分析原理解析:优化Java程序性能和内存利用效率
|
10天前
|
存储 缓存 监控
深入解析JVM内存分配优化技术:TLAB
深入解析JVM内存分配优化技术:TLAB
|
11天前
|
存储 安全 Java
深入理解Java内存模型(JMM)与虚拟机的内存结构(JVM)
深入理解Java内存模型(JMM)与虚拟机的内存结构(JVM)