部分文章内容为网上转载整合,并在博客中记录,以便查阅,部分原文出处未进行标注,如有侵权,请联系我,谢谢。邮箱地址:gnivor@163.com ►►►需要气球么?请点击我吧!

JVM笔记-逃逸分析

参考:

http://www.iteye.com/topic/473355
http://blog.sina.com.cn/s/blog_4b6047bc01000avq.html

 

什么是逃逸分析(Escape Analysis)?

在编程语言的编译优化原理中,分析指针动态范围的方法称之为逃逸分析。它跟静态代码分析技术中的指针分析和外形分析类似。
通俗一点讲,当一个对象的指针被多个方法线程引用时,我们称这个指针发生了逃逸。
而用来分析这种逃逸现象的方法,就称之为逃逸分析。
举个例子:

class A {
  public static B b;
  public void globalVariablePointerEscape() { // 给全局变量赋值,发生逃逸
    b = new B();
  }
 
  public B methodPointerEscape() { // 方法返回值,发生逃逸
    return new B();
  }
 
  public void instancePassPointerEscape() {
    methodPointerEscape().printClassName(this); // 实例引用传递,发生逃逸
  }
}
 
class B {
  public void printClassName(A a) {
    System.out.println(a.class.getName());
  }
}

在这个例子中,一共举了3种常见的指针逃逸场景。分别是 全局变量赋值,方法返回值,实例引用传递。

 

逃逸分析优化JVM原理

我们知道java对象是在里分配的,在调用中,只保存了对象的指针

当对象不再使用后,需要依靠GC来遍历引用树并回收内存,如果对象数量较多,将给GC带来较大压力,也间接影响了应用的性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。

怎么减少临时对象在堆内的分配数量呢?不可能不实例化对象吧!

 

场景介绍

其实,在java应用里普遍存在一种场景。一般是在方法体内,声明了一个局部变量,且该变量在方法执行生命周期内未发生逃逸(在方法体内,未将引用暴露给外面)。

按照JVM内存分配机制,首先会在堆里创建变量类的实例,然后将返回的对象指针压入调用栈,继续执行。

这是优化前,JVM的处理方式。

 

逃逸分析优化 - 栈上分配

优化原理:分析找到未逃逸的变量,将变量类的实例化内存直接在栈里分配(无需进入堆),分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量对象也被回收

这是优化后的处理方式,对比可以看出,主要区别在栈空间直接作为临时对象的存储介质。从而减少了临时对象在堆内的分配数量。

例子

public void my_method(){
    V v=new V();
    //use v
    ......
    v=null;
}
    在这个方法中创建的局部对象被赋给了v,但是没有返回,没有赋给全局变量等等操作,因此这个对象是没有逃逸的,是可以在运行时栈进行分配和销毁的对象。没有发生逃逸的对象由于生命周期都在一个方法体内,因此它们是可以在运行时栈上分配并销毁。

 

逃逸分析的原理很简单,但JVM在应用过程中,还是有诸多考虑。

比如,逃逸分析不能在静态编译时进行,必须在JIT里完成。原因是,与java的动态性有冲突。因为你可以在运行时,通过动态代理改变一个类的行为,此时,逃逸分析是无法得知类已经变化了。

 

逃逸分析另一个重要的优化 - 同步消除

如果你定义的类的方法上有同步锁,但在运行时,却只有一个线程在访问,此时逃逸分析后的机器码,会去掉同步锁运行。

 

======================================================

性能测试

来自 http://blog.uncommons.org/ 性能测试结果。

测试场景1:

生成几百万个随机数,然后做一些少量运算。

VM 参数: -server
95 秒
VM 参数: -server -XX:+DoEscapeAnalysis
73 秒

性能提高: 23%

测试场景2:

非负矩阵分解算法。

VM 参数: -server
22.6 秒
VM 参数: -server -XX:+DoEscapeAnalysis
20.8 秒

性能提升: 8%

JVM中启用逃逸分析 DoEscapeAnalysis

安装jdk1.6.0_14,运行java时传递jvm参数  -XX:+DoEscapeAnalysis

逃逸分析还能用于以下优化场景,但在JVM中未知使用。

1,标量替换(Scalar Replacement)

2,减小竞争检测范围

3,基于区域的内存分配

 

posted @ 2016-11-03 19:53  流了个火  阅读(1141)  评论(0编辑  收藏  举报
►►►需要气球么?请点击我吧!►►►