JVM的逃逸分析

对象必定分配在堆中吗?java

JVM经过逃逸分析,那些逃不出方法的对象会在栈上分配。优化

什么是逃逸分析?线程

EscapeAnalysis,逃逸分析,指的是虚拟机在运行期经过计算分析将本来在堆上分配的对象改为在栈中分配,这样的好处是栈上分配的对象随着线程的结束而自动销毁,不依赖于GC,能够下降垃圾收集器运行的频率。code

如何断定为逃逸?对象

JVM判断新建立的对象是否逃逸的依据有两个:内存

  1. 对象被赋值给堆中对象的字段和类的静态变量
  2. 对象被传进了不肯定的代码中去运行

若是知足了以上状况的任意一种,那这个对象JVM就会断定为逃逸,对以上两种状况举例,样例来源于:https://zhuanlan.zhihu.com/p/59215831get

public class EscapeTest {

    public static Object globalVariableObject;

    public Object instanceObject;

    public void globalVariableEscape(){
        globalVariableObject = new Object(); // 静态变量,外部线程可见,发生逃逸
    }

    public void instanceObjectEscape(){
        instanceObject = new Object(); // 赋值给堆中实例字段,外部线程可见,发生逃逸
    }
    
    public Object returnObjectEscape(){
        return new Object();  // 返回实例,外部线程可见,发生逃逸
    }

    public void noEscape(){
        Object noEscape = new Object();  // 仅建立线程可见,对象无逃逸
    }

}

Java的逃逸分析只能发生在即时编译(JIT)期,为何不能在静态编译(javac)中?同步

参考R大回答:https://www.zhihu.com/questio...虚拟机

总结来讲是能够发生在静态编译期的,可是Java的分离编译和动态加载使得前期的静态编译的逃逸分析比较困难或收益较少,因此目前Java的逃逸分析只发在JIT的即时编译中,由于收集到足够的运行数据JVM能够更好的判断对象是否发生了逃逸。io

JVM开启逃逸分析之后的优点?

Java8+默认是开启的, -XX:+DoEscapeAnalysis
  1. 栈上分配,虚拟机参数:-XX:+PrintGC -Xms5M -Xmn5M -XX:+DoEscapeAnalysis

    • 这种优化能够下降垃圾收集器运行的频率,这样每当方法出栈,对象内存随之释放。

      public static void main(String[] args) {
          for(int i = 0; i < 5000000; i++) {
              createObject();
          }
      }
      
      public static void createObject() {
          new Object();
      }
  2. 同步消除

    • 若是发现某个对象只能从一个线程可访问,那么在这个对象上的操做能够不须要同步。
  3. 标量替换

    • 若是某个对象的访问方式不要求该对象是一个连续的内存结构,那么对象的部分(或所有)能够不存储在内存,而是存储在CPU寄存器中。简单来讲就是把对象分解成一个个基本类型,而且内存分配再也不是分配在堆上,而是分配在栈上。这样的好处有,1、减小内存使用,由于不用生成对象头。 2、程序内存回收效率高,而且GC频率也会减小。
相关文章
相关标签/搜索