斯人已戒

逃逸分析

/*************************************逃逸分析*********************************/

一个java文件如果要解析为可在计算机上执行的指令,需要经过2个阶段:
1 javac命令,.java文件被编译成.class文件
2 需要运行时,jvm解释器解释.class的字节码将其翻译成机器指令,逐条读取和翻译(翻译一下再执行肯定比直接执行二进制字节码执行慢),为了提升效率,引入了即时编译技术----JIT,当jvm发现某些方法和代码经常执行时,
会将其缓存为HOT SPOT CODE (热点代码:指令集合)

逃逸分析: jit工作时,会分析对象的作用域,当一个对象在一个方法内部被定义,然后也可以在方法外部被调用,比如作为返回值返回,那么这个对象就时方法逃逸,如果可别其他线程调用,那就是线程逃逸

比如如下代码:

//这就是方法逃逸
public static StringBuffer append(String a,String b){
StringBuffer buffer = new StringBuffer();
buffer.append(a);
buffer.append(b);
return buffer;
}

//方法未逃逸
public static String append(String a,String b){
StringBuffer buffer = new StringBuffer();
buffer.append(a);
buffer.append(b);
return buffer.toString();
}

逃逸分析后可以对代码做出以下优化:

1 同步省略,即发现对象只会被一个线程访问到,那么线程进入同步块的时候不会加锁
2 堆内存分布转为栈内存分配,即发现一个对象只在一个方法内创建且只在这个方法内使用,不产生逃逸,那么这个对象会分配在栈内,使用完后可以直接回收
3 分离对象或标量替换 即发现一个对象不需要连续的内存结构也可以被访问到,那么这个对象的部分或者是全部可以不存储在内存中,而是在cpu寄存器中
标量(scalar) 是一个小的无法再分解的数据块,比如java的基本数据类型都是标量,那些还能再分解的数据叫做聚合量,比如java的一些objec对象;

经过jit的逃逸分析,发现一个对象不被方法外界访问,那么jit会优化,将其分解成若干个成员变量来代替它,这个过程就是标量替换,示例如下:
class point{
int x;
int y;
}

public static void alloc(){
point pi = new point(1,2);
sout(pi.x+" "+pi.y);
}

经过jit优化,alloc的代码会被优化为:
public static void alloc(){
int x=1;
int y=2;
sout(x+" "+y);
}
这样就减少了不必要对象的创建,节约内存

jdk1.7开始默认开启逃逸分析 如果需要关闭,使用 -XX:-DoEscapeAnalysis

 

posted on 2020-09-16 12:01  斯人已戒  阅读(70)  评论(0编辑  收藏  举报

导航