注:主要参考自《分布式java应用:基础与实践》《深刻理解Java虚拟机(第二版)》html
一、两种执行方式:java
注意:分布式
查看当前机器默认是client模式仍是server模式,使用:"java -version"命令,以下ide
其中,mixed mode表示"解释执行+编译执行"的混合模式性能
二、解释执行优化
查看 第三章 类文件结构与javap的使用 中的inc()方法的执行spa
或者查看《深刻了解java虚拟机(第二版)》P272-P275线程
三、编译执行3d
四、C1优化code
说明:关于所有的优化技术列表,查看《深刻理解java虚拟机(第二版)》P346-P347
只作少许性能开销比高的优化,占用内存少,主要的优化包括:
4.一、方法内联、冗余消除、复写传播、消除无用代码
4.1.一、方法内联
方法内联含义:假设方法A调用了方法B,把B的指令直接植入到A中。
static class B{ int value; final int get() { return value; } } public void foo() { y = b.get(); //do something z = b.get(); sum = y + z; }
说明:在上述代码中,b是B的一个实例。
方法内联以后,
public void foo() { y = b.value; //do something z = b.value; sum = y + z; }
方法内联的条件:
方法内联的地位:
4.1.二、冗余消除
冗余消除:如上边的两个b.value冗余(前提,在do something部分没有对b.value进行操做,这也是咱们在作优化以前须要先收集数据的缘由)
假设在do something部分没有对b.value进行操做,进行冗余消除后,
public void foo() { y = b.value; //do something z = y; sum = y + z; }
4.1.三、复写传播
固然,在冗余消除后,JIT对上述的代码进行分析,发现变量z没用(能够彻底用y来代替),进行"复写传播"以后,
public void foo() { y = b.value; //do something y = y; sum = y + y; }
4.1.四、无用代码消除
在"复写传播"后,发现"y=y"是无用代码,因此能够进行"无用代码的消除"操做,消除以后,
public void foo() { y = b.value; //do something sum = y + y; }
须要说明的是,这里的"无用代码的消除"是在前三部优化的基础上来作的,而javac编译中"语义分析"部分的"无用代码的消除"是直接消除一些直接写好的代码(例如:if(false){})
4.二、类型继承关系分析、去虚拟化
public interface Animal { public void eat(); } public class Cat implements Animal{ public void eat() { System.out.println("cat eat fish"); } } public class Test{ public void methodA(Animal animal){ animal.eat(); } }
首先分析Animal的整个"类型继承关系",发现只有一个实现类Cat,那么在methodA(Animal animal)的代码就能够优化为以下,
public void methodA(Animal animal){ System.out.println("cat eat fish"); }
可是,若是以后在运行过程当中,"类型继承关系"发现Animal又多了一个实现类Dog,那么此时就不在执行以前优化编译好的机器码了,而是进行解释执行,即以下的"逆优化"。
逆优化:
当编译后的机器码的执行再也不符合优化条件,则该机器码对应的部分回到解释执行。
eg.好比"去虚拟化",若是编译以后,发现类的实现方法多于一种了,此时就要执行"逆优化"
五、C2优化
进行了大量优化,占用内存多,适用于服务端程序,对于C2优化,除了具备C1的优化措施后,还有不少优化。
逃逸分析(辅助):
开启:-XX:+DoEscapeAnalysis
根据运行情况来判断方法中的变量是否会被方法或外部线程所读取,若不会,此变量是不逃逸的。基于此,C2在编译时会作:
5.一、标量替换
含义:将一个java对象打散,根据程序,将该对象中的属性做为一个个标量来使用。
Point point = new Point(1,2); System.out.println("point.x:" + point.x + ",point.y:" + point.y); //do after
若在//do after中(即前边两句代码以后的全部代码中)再没有其余代码访问"point对象"了,则将"point对象"打散并进行标量替换,
int x = 1; int y = 2; System.out.println("point.x:" + x + ",point.y:" + y);
好处:
5.二、栈上分配
含义:肯定一个方法的变量不会逃逸出当前方法以外(即该变量不会被其余方法引用),则该变量能够直接分配在栈上,随方法执行结束,栈帧消失,该变量也消失,减轻GC压力。
好处:
5.三、同步削除
含义:肯定一个方法的变量不会逃逸出当前线程以外(即该变量不会被其余线程使用),则对于该变量的同步策略就消除掉,以下,
synchronized(cat){ //do xxx }
若cat不会逃逸出当前线程,则同步块能够去掉,以下,
//do xxx
总结:
解释器:
JIT编译器:
注意: