JVM的逃逸分析
- - SegmentFault 最新的文章JVM通过逃逸分析,那些逃不出方法的对象会在栈上分配. EscapeAnalysis,逃逸分析,指的是虚拟机在 运行期通过计算分析将原本在堆上分配的对象改成在栈中分配,这样的好处是栈上分配的对象随着线程的结束而自动销毁,不依赖于GC,可以降低垃圾收集器运行的频率. JVM判断新创建的对象是否逃逸的依据有两个:.
对象一定分配在堆中吗?
JVM通过逃逸分析,那些逃不出方法的对象会在栈上分配。
什么是逃逸分析?
EscapeAnalysis,逃逸分析,指的是虚拟机在 运行期
通过计算分析将原本在堆上分配的对象改成在栈中分配,这样的好处是栈上分配的对象随着线程的结束而自动销毁,不依赖于GC,可以降低垃圾收集器运行的频率。
如何判定为逃逸?
JVM判断新创建的对象是否逃逸的依据有两个:
如果满足了以上情况的任意一种,那这个对象JVM就会判定为逃逸,对以上两种情况举例,样例来源于: https://zhuanlan.zhihu.com/p/59215831
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可以更好的判断对象是否发生了逃逸。
JVM开启逃逸分析以后的优势?
Java8+默认是开启的, -XX:+DoEscapeAnalysis
栈上分配,虚拟机参数: -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();
}
同步消除
标量替换