内存逃逸
逃逸分析,其实就是分析一个对象是否会逃逸出方法,分析对象的动态作用域。如果一个对象在一个方法内定义,并且有可能被方法外部引用使用,那认为它逃逸了。
public static StringBuffer craeteStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb; }
public static String createStringBuffer(String s1, String s2) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); return sb.toString(); } 复制代码 第一段代码中的sb就逃逸了,而第二段代码中的sb就没有逃逸。 |
JDK1.7 开始,逃逸分析默认是开启的,可以通过以下参数进行启停。
# 开启
-XX:+DoEscapeAnalysis
# 关闭
-XX:-DoEscapeAnalysis
如果分析一个对象没有逃逸出方法的时候,就有可能被分配到栈上。执行完就清理了,这样就不需要在堆中进行 GC 回收,提高了性能。
示例:
-XX:-DoEscapeAnalysis 关闭逃逸分析
-XX:+DoEscapeAnalysis 开启逃逸分析 默认的
锁消除
通过逃逸分析来判断同步块所使用的锁是否只被一个线程访问而没有被发布到其他线程,没有则可以取消这个锁,锁消除就是从这来的。
标量替换
标量是指不可分割的量,如java中基本数据类型和reference类型,相对的一个数据可以继续分解,称为聚合量;
如果把一个对象拆散,将其成员变量恢复到基本类型来访问就叫做标量替换;
如果逃逸分析发现一个对象不会被外部访问,并且该对象可以被拆散,那么经过优化之后,并不直接生成该对象,而是在栈上创建若干个成员变量;
通过-XX:+EliminateAllocations可以开启标量替换, -XX:+PrintEliminateAllocations查看标量替换情况。