`

JVM优化之逃逸分析(Escape Analysis)

    博客分类:
  • JVM
jvm 
阅读更多
转载自 ---- http://kenwublog.com/jvm-optimization-escape-analysis

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

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

Java代码

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带来较大压力,也间接影响了应用的性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。

接下来,举一个场景来阐述。
假设在方法体内,声明了一个局部变量,且该变量在方法执行生命周期内未发生逃逸(在方法体内,未将引用暴露给外面)。
按照JVM内存分配机制,首先会在堆里创建变量类的实例,然后将返回的对象指针压入调用栈,继续执行。
这是优化前,JVM的处理方式。

逃逸分析优化 – 栈上分配
优化原理:分析找到未逃逸的变量,将变量类的实例化内存直接在栈里分配(无需进入堆),分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量也被回收。
这是优化后的处理方式,对比可以看出,主要区别在栈空间直接作为临时对象的存储介质。从而减少了临时对象在堆内的分配数量。

逃逸分析另一个重要的优化 – 锁省略
如果通过逃逸分析能够判断出指向某个局部变量的多个引用被限制在同一方法体内,并且所有这些引用都不能“逃逸”到这个方法体以外的地方,那么HotSpot会要求JIT执行一项优化动作 – 将局部变量上拥有的锁省略掉。
这就是锁省略(lock elision)。
性能测试

class DoubleSlot {
    final int value1;
    final int value2;

    public DoubleSlot(int value1, int value2) {
      this.value1 = value1;
      this.value2 = value2;
    }
  }

  static int slotValue(DoubleSlot slot) {
    return slot.value1 + slot.value2;
  }

  static int sum(int[] values) {
    int sum = 0;
    int length = values.length;
    for(int i=1; i<100; i++)
      sum(values);

    for(int i=0; i<100; i++)
      test(values);
  }

测试结果是:
$ /usr/jdk/jdk1.6.0_14/bin/java -server EscapeAnalysisTest
time 8889261

$ /usr/jdk/jdk1.6.0_14/bin/java -server -XX:+DoEscapeAnalysis?EscapeAnalysisTest
time 1408140

从结果中,可以看到,启用逃逸分析的运行性能6倍于未启用。
JVM中启用逃逸分析 DoEscapeAnalysis

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

参考资料:
http://www.cag.csail.mit.edu/~rinard/pointer_and_escape_analysis/
http://developer.amd.com/documentation/Articles/pages/01302008_jvm.aspx
http://en.wikipedia.org/wiki/Escape_analysis
http://en.wikipedia.org/wiki/Java_performance#Escape_analysis_and_lock_coarsening
http://staff.ustc.edu.cn/~yuzhang/papers/cncc07.pdf (一种实现方法,过于学术,不过引言部分写得很不错)
http://java.dzone.com/articles/escape-analysis-java-6-update
http://en.wikipedia.org/wiki/Non-negative_matrix_factorization

转载请注明原文链接:http://kenwublog.com/jvm-optimization-escape-analysis
分享到:
评论

相关推荐

    深入JVM系列-逃逸分析、同步省略、栈上分配、标量替换1

    逃逸分析(Escape Analysis)是Java虚拟机中的一个重要优化技术,它通过对程序进行跨函数全局的数据流分析,判断一个新创建的对象是否会被外部方法或者外部线程访问。如果分析结果显示对象不会逃逸出当前作用域,JVM...

    java中jvm逃逸问题分析

    JVM 逃逸分析(Escape Analysis)是一种可以有效减少 Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot 编译器能够分析出一个新的对象的引用的使用范围,从而决定是否...

    原创-JVM调优

    此外,对于频繁创建和销毁的小对象,可以考虑使用栈上分配(Stack Allocation)或逃逸分析(Escape Analysis)来避免不必要的堆分配,提升性能。总之,深入理解JVM的工作原理是进行有效调优的前提。

    jvm-anatomy-park-complete

    锁粗化是逃逸分析技术(Escape Analysis)的一个应用,其目的是减少多线程中锁的竞争和同步开销。它通过合并相邻的几个锁定区域来实现这一点,从而减少锁定操作的频率。 锁粗化这一概念其实可以类比为编译器优化中...

    Java虚拟机的运行时优化

    6. **逃逸分析(Escape Analysis)**: 逃逸分析是一种用于确定对象生命周期和分配方式的技术。如果分析发现对象不会逃出当前作用域,JVM可能会将对象分配在栈上,从而避免GC的开销。 7. **并发与多线程优化**: ...

    JVM 50道面试题和答案.docx

    - 对于某些没有逃逸出方法的对象,JVM可能会进行栈上分配(Stack Allocation)或者逃逸分析(Escape Analysis),这使得这些对象可以直接在栈帧中创建,从而提高效率。 2. **JVM常量池**: - JDK 1.8之前,字符串...

    The Influence of Alias and References Escape on Java Program Analysis

    5. 编译器优化:编译器在编译Java代码时会进行各种优化,例如逃逸分析(Escape Analysis)是Java虚拟机(JVM)中的一个特性,用于决定对象的分配地点及生命周期。如果编译器能准确分析出引用不逃逸,则可以进行栈上...

    java 实时编程

    在Java的实时编程中,还有一些关键特性,如逃逸分析(Escape Analysis)、标量替换(Scalar Replacement)、锁消除(Lock Elimination)和死代码消除(Dead Code Elimination)等。这些优化技术有助于减少内存分配、...

    浅谈Java虚拟机对内部锁的四种优化方式

    锁消除是指JIT(Just-In-Time)编译器通过逃逸分析(Escape Analysis)来确定同步块中的锁对象是否只被单个线程访问,而不会被其他线程共享。如果确定对象不会逃逸,JIT编译器会直接消除同步代码块中的锁操作,从而...

    jea:Java转义分析

    这种方法被称为栈上复用(Stack Allocation)或逃逸分析(Escape Analysis)。 4. **优化决策**:根据分析结果,JVM可以做出其他优化决策,比如是否启用标量替换(Scalar Replacement),即将对象的字段拆分为独立的...

    jdk7 javac源码

    JDK 7引入了一些编译优化策略,比如逃逸分析(Escape Analysis),可以减少对象创建的开销,提高程序性能。 5. **多线程支持**: 在编译过程中,javac可能需要处理多线程问题,比如并行编译,这在源码中会有相应...

    性能飞跃的催化剂:揭秘Java JIT编译器的魔法

    - **逃逸分析(Escape Analysis)**:分析对象的作用域,如果一个对象在其作用域内不会被其他方法引用,则可以考虑在栈上分配内存,而不是在堆上分配,从而减少了垃圾回收的压力。 - **死代码消除(Dead Code ...

    JDK1.6中文帮助文档二

    - **逃逸分析(Escape Analysis)**: 有助于减少无用对象的创建,提高程序效率。 - **类型推断(Type Inference)**: 在泛型使用中,编译器可以自动推断类型,使得代码更加简洁。 3. **Java虚拟机(JVM)改进**:...

    Java开发JDK,jdk1.6(JDK6)

    - **逃逸分析(Escape Analysis)**:用于优化内存分配,可以减少短生命周期对象在堆上的分配,提高程序性能。 3. **JVM改进** - **垃圾收集(Garbage Collection)**:JDK6引入了并行的Full GC,提升了全堆清理的...

    Compiler-Grouop-Optimisation:COMP0147

    2. **逃逸分析(Escape Analysis)**:分析对象生命周期,判断其是否能逃逸出当前的作用域。如果不能,可以优化为栈上分配或标量替换,避免不必要的内存分配。 3. **循环展开(Loop Unrolling)**:减少循环迭代...

    java中final修饰符的使用方法

    `final`关键字还可以影响JVM的优化,尤其是逃逸分析(Escape Analysis)。当JVM确定一个对象不会被外部访问时,可能会将其存储在栈上,从而提高效率。此外,对于`final`基本类型的局部变量,JVM可能会使用标量替换...

Global site tag (gtag.js) - Google Analytics