前人栽树:传送门
逃逸分析个人理解主要是为了优化gc的技术
文章中还提到了锁消除,如果锁对象不发生逃逸,会自动消除synchronized块
public String concatString(String s1, String s2, String s3){
return s1 + s2 + s3;
}
大家都知道,编译器会对String的连接做自动优化。jdk5之前,会转化为StringBuffer对象的连续append()操作,jdk5及之后,会转化为StringBulider对象的连续append()操作。所以上述代码可能会编译为如下代码:
public String concatString(String s1, String s2, String s3){
StringBuffer sb = new StringBuffer();
sb.append(s1).append(s2).append(s3);
return sb.toString();
}
讲锁消除,就以StringBuffer为例吧。StringBuffer.append()都是同步块,锁是sb对象。但因为sb对象作用域被限制在concatString()方法内部,也就是说sb所有引用都不会逃逸到concatString()方法之外,其他线程无法访问到sb对象。因此,就算append()有锁,也可以被完全消除掉,在即使编译之后,这段代码就会忽略所有同步而直接执行。
上述代码还能再说一下,如果sb发生逃逸,那么三次append()会加锁三次吗?答案是不会的,因为虚拟机探测到这样一连串操作都是对同一个对象加锁,就会将加锁同步的范围扩展到整个操作序列的外部,即扩展到第一个append()操作之前,直至最后一个append()操作之后,这样只需要加一次锁就可以了,这就是锁粗化。
java中还有一个叫this引用逃逸(传送门)