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