对象必定分配在堆中吗?java
JVM经过逃逸分析,那些逃不出方法的对象会在栈上分配。优化
什么是逃逸分析?线程
EscapeAnalysis,逃逸分析,指的是虚拟机在运行期
经过计算分析将本来在堆上分配的对象改为在栈中分配,这样的好处是栈上分配的对象随着线程的结束而自动销毁,不依赖于GC,能够下降垃圾收集器运行的频率。code
如何断定为逃逸?对象
JVM判断新建立的对象是否逃逸的依据有两个:内存
若是知足了以上状况的任意一种,那这个对象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
栈上分配,虚拟机参数:-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(); }
同步消除
标量替换