java逃逸是什么东西?
我怎么知道是否开启了逃逸分析?
为什么对象可以不在堆上分配内存?
代码示例
1.java逃逸是什么东西?
可以理解为jvm为了减少GC和优化内存使用做出的一种优化方案,由JIT动态编译器进行优化,所以通过反编译是看不出来的
2.我怎么知道是否开启了逃逸分析?
逃逸分析的JVM参数是 DoEscapeAnalysis,通过java -client -XX: PrintFlagsInitial 打印一下JVM参数默认值(我这里是1.8版本)
3.为什么对象可以不在堆上分配内存?
JVM逃逸做了如下几种对代码的优化,锁消除,标量替换等手段,将对象所需空间在栈中分配,减少gc回收,锁消除的JVM参数是EliminateLocks ,标量替换是EliminateAllocations,还是通过上面方法去搜索,发现默认是开启的(1.8版本)
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); }
联系客服