JVM少为人知的秘密(一)
1. 对象一定分配在堆中吗?
不一定哦,JVM通过「逃逸分析」技术,那些逃不出方法的对象会在栈上分配
2. 什么是逃逸分析技术?
逃逸分析(Escape Analysis),是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围,从而决定是否要将这个对象分配到堆上。
逃逸分析是指分析指针动态范围的方法,它同编译器优化原理的指针分析和外形分析相关联。当变量(或者对象)在方法中分配后,其指针有可能被返回或者被全局引用,这样就会被其他方法或者线程所引用,这种现象称作指针(或者引用)的逃逸(Escape)。通俗点讲,如果一个对象的指针被多个方法或者线程引用时,那么我们就称这个对象的指针发生了逃逸。
3. 举个栗子?
public class EscapeAnalysisTest {
public static Object object;
//StringBuilder可能被其他方法改变,发生逃逸
public StringBuilder escape(String a, String b) {
StringBuilder str = new StringBuilder();
str.append(a);
str.append(b);
return str;
}
//不直接返回StringBuffer,不发生逃逸
public String notEscape(String a, String b) {
StringBuilder str = new StringBuilder();
str.append(a);
str.append(b);
return str.toString();
}
//object外部线程可见,发生逃逸
public void objectEscape(){
object = new Object();
}
//object仅方法内部可见,不发生逃逸
public void objectNotEscape(){
Object object = new Object();
}
}
4. 好处?
- 栈上分配:不会逃逸的对象可以在栈上分配,既减少内存的使用(不用生成对象头),又降低GC(垃圾收集器)运行的频率
- 消除同步:不会逃逸的对象意味着只能从一个线程访问,所以对这个对象的操作可以不需要同步