逃逸分析:
当一个Java对象被定义后,可能会被外部方法引用
在JDK 6之后支持对象的栈上分析和逃逸分析,在JDK 7中完全支持栈上分配对象。 其是否打开逃逸分析依赖于以下JVM的设置:
-XX:+DoEscapeAnalysis
方法逃逸:
被当作参数传递到了其他方法中
线程逃逸:
被其他线程访问
锁消除:
能证明Java对象不会逃避到其他线程,不可能存在竞争却申请锁的代码段,则消除同步锁,代码的执行效率会更高
栈上分配
能证明Java不会逃逸到其他方法中,该对象分配内存空间时,可直接进行“栈上分配”(不需要GC,自动销毁)
栈上分配可以提升代码性能,降低在多线程情况下的锁使用,但是会受限于其空间的大小
标量替换:
能证明 Java不会逃逸到其他方法中,该Java类结构比较简单(可拆分成标量,也即最原始的基本类型)时,HopSpot会将Java对象实例直接分配在当前线程所关联的高速缓存中
逃逸分析 测试案例
1、开启逃逸分析Demo:
-server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations
public class OnStackTest {
public static class User{
public int id = 0;
public String name = "";
}
public static void alloc(){
User u = new User();
u.id = 5;
u.name = "geym";
}
public static void main(String[] args) {
long b = System.currentTimeMillis();
for(int i = 0;i< 100000000;i++){
alloc();
}
long e = System.currentTimeMillis();
System.out.println("main进程 结束 :"+ (e-b));
}
}
2、栈上分配 Demo
-server -Xmx10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations
public class OnStackTest {
public static class User{
public int id = 0;
public String name = "";
}
public static void alloc(){
User u = new User();
u.id = 5;
u.name = "geym";
}
public static void main(String[] args) {
long b = System.currentTimeMillis();
for(int i = 0;i< 100000000;i++){
alloc();
}
long e = System.currentTimeMillis();
System.out.println("main进程 结束 :"+ (e-b));
}
}
3、锁消除 Demo
-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks -Xcomp -XX:-BackgroundCompilation -XX:BiasedLockingStartupDelay=0
public class LockEliminate {
private static final int CIRCLE = 20000000;
public static void main(String[] args) throws InterruptedException{
long start = System.currentTimeMillis();
for(int i =0 ; i< CIRCLE;i++){
createStringBuffer("JVM","okxuewei");
}
long bufferCost = System.currentTimeMillis()-start;
System.out.println("createStringBuffer: "+bufferCost+" ms");
}
public static String createStringBuffer(String s1,String s2){
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
}