逃逸分析和栈上分配

逃逸分析:

当一个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();
    }

}
发布了32 篇原创文章 · 获赞 15 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/okxuewei/article/details/88775176