java 逃逸分析_Java逃逸分析

java逃逸是什么东西?

我怎么知道是否开启了逃逸分析?

为什么对象可以不在堆上分配内存?

代码示例

1.java逃逸是什么东西?

可以理解为jvm为了减少GC和优化内存使用做出的一种优化方案,由JIT动态编译器进行优化,所以通过反编译是看不出来的

2.我怎么知道是否开启了逃逸分析?

逃逸分析的JVM参数是 DoEscapeAnalysis,通过java -client -XX: PrintFlagsInitial 打印一下JVM参数默认值(我这里是1.8版本)

169532755_1_20190828120151738.png

可以发现默认是开启了逃逸分析。

3.为什么对象可以不在堆上分配内存?

JVM逃逸做了如下几种对代码的优化,锁消除,标量替换等手段,将对象所需空间在栈中分配,减少gc回收,锁消除的JVM参数是EliminateLocks ,标量替换是EliminateAllocations,还是通过上面方法去搜索,发现默认是开启的(1.8版本)

169532755_2_20190828120151988.png

169532755_3_2019082812015297.png

4.代码示例

首先是锁消除,对象在方法内创建,并且在方法内加锁,这样是没有意义的,每一次调用方法都会new新的对象,并对新的对象加锁private void sync() {

Object o = new Object();

synchronized(o) {

System.out.println(o);

}

}

jit动态编译代码优化为private void sync(){

Object o = new Object();

System.out.println(o);

}

在方法内部创建一个没有被外部引用的对象,就会不会发生逃逸,但是如果像下图这种,方法内部的对象被拿到外部使用了那么就发生了逃逸private StringBuilder sync(String a,String b){

StringBuilder sb = new StringBuilder();

sb.append(a);

sb.append(b);

return sb;

}

如果对象仅仅在方法内部使用,不将引用传递出去,是不会发生逃逸的,比如改成这样private String sync(String a,String b){

StringBuilder sb = new StringBuilder();

sb.append(a);

sb.append(b);

return sb.toString();

}

这样StringBuilder 的引用就消失了,会顺利的被回收掉,下面是标量替换,对象在方法内创建,无外部引用,会被标量所替换,减少GC和堆上内存使用private void sync() {

Sync sync= new Sync(1,2);

System.out.println("x" sync.x "y" sync.y);

}

class Sync{

public Sync(int x, int y) {

this.x = x;

this.y = y;

}

private int x;

private int y;

}

替换结果private void sync(){

int x = 1;

int y = 2;

System.out.println("x" sync.x "y" sync.y);

}https://www.icode9.com/content-1-418951.html


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部