【Java虚拟机】虚拟机的逃逸分析

引子

在网上看过这么一个面试题:Java中的创建对象一定是在Java堆中分配内存么?为什么?

看完一脸懵逼,对象不是都在Java堆中?秉着面向百度编程的原则,我发现了一个新奇的概念:逃逸分析。

逃逸分析

首先我们了解什么是逃逸分析:

逃逸分析的基本行为就是分析对象的动态作用域:当一个对象在方法中被定义后,它可能被外部的方法所引用,例如作为方法返回值或者被当作调用参数传入其他方法中,称为方法逃逸。甚至还有可能被其他线程访问到,例如赋值给类变量或者可以在其他线程中访问的实例变量,称为线程逃逸。

如果能够证明一个对象不会逃逸到线程或者方法之外,这就是其他方法或者线程无法通过任何途径访问到这个实例,则可能对这个变量进行一些高效的优化:

  • 栈上分配:如果确定一个对象不会逃逸出方法之外,就让这个对象在栈上分配内存,那么这个对象所占用的内存空间就会随着栈帧的出栈而被回收。
  • 同步消除:如果确定一个对象不会逃逸出线程之外,即无法被其他线程访问到,那么这个变量在进行读写操作时一定不会有竞争,对这个变量的同步措施也可以消除掉。
  • 标量替换:标量就是不可再被拆分的变量,例如Java中的基本数据类型和reference类型,都不可被拆分,它们就可以被称之为标量。相对的,如果一个变量可以被分解,那么它就称为聚合量,Java中的对象就是最典型的聚合量。如果逃逸分析证明一个变量不会被外部访问,并且这个对象可以被分解的,那么程序真正执行的时候可能不会创建这个对象,而改为直接创建这个对象若干个被这个方法使用到的成员变量来代替。对象拆分以后,除了有很大的概率让对象的成员变量在栈上分配和读写以外,还可以为后续进一步的优化创建条件。

结论

至此,我们就知道了,对象不仅可以在Java堆中分配内存,如果该对象被逃逸分析确定不会逃逸出方法之外,那么这个对象就可以在栈中分配内存了。

你可能感兴趣的:(Java)