JVM学习笔记-程序优化与代码编译
if(true){Code}->Code?
?
11.ServerCompiler又称为C2,C2采用了大量的传统编译优化技巧来进行优化,占用内存相对会多些,适合与服务器端的应用。寄存器分配策略上C2采用的为传统的图着色寄存器分配算法,由于C2会收集程序的运行信息,因此其优化的范围更多在于全局的优化。收集的信息主要有:分支的跳转/不跳转的频率、某条指令上出现过的类型、是否出现过空值、是否出现过异常。
1)?逃逸分析:当一个对象在方法里面被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中,这种行为称为方法逃逸。甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,这种行为称为线程逃逸。用户可以使用参数-XX:+DoEscapeAnalysis来手动开启逃逸分析。
2)?栈上分配:如果确定一个对象不会逃逸出方法之外,那让这个对象在栈上分配内存将会是一个很不错的主意,对象所占用的内存空间就可以随栈帧出栈而销毁。
3)?同步消除:线程同步本身就是一个相对耗时的过程,如果逃逸分析能够确定一个变量不会逃逸出线程,无法被其他线程访问,那这个变量的读写肯定就不会有竞争,对这个变量实施的同步措施也就可以消除掉。
4)?标量替换:如果把一个Java对象拆散,根据程序访问的情况,将其使用到的成员变量恢复原始类型来访问就叫做标量替换。如果逃逸分析证明一个对象不会被外部访问,并且这个对象可以被拆散的话,那程序真正执行的时候将可能不创建这个对象,而改为直接创建它的若干个被这个方法使用到的成员变量来代替。
出了C1、C2外,还有一种较为特殊的编译为:OSR(On Stack Replace)。OSR编译和C1、C2最主要的不同点在于OSR编译只替换循环代码的入口,而C1、C2替换的是方法调用的入口,因此在OSR编译后会出现的现象是方法的整段代码被编译了,但只有在循环代码体部分才执行编译后的机器码,其他部分则仍然是解释执行方式。