1.逃逸分析
逃逸分析只是一种分析,是为其他优化手段提供分析支撑,它本身并不做优化。逃逸分析是分析方法体的局部变量的作用范围是否会逃出方法体。
逃逸分析包括:
(1)全局变量赋值逃逸
public class EscapeAnalysis {
public static Object object;
public void globalVariableEscape(){//全局变量赋值逃逸
object =new Object();
}
public Object methodEscape(){ //方法返回值逃逸
return new Object();
}
public void instancePassEscape(){ //实例引用发生逃逸
this.speak(this);
}
public void speak(EscapeAnalysis escapeAnalysis){
System.out.println("Escape Hello");
}
}
(2)方法返回值逃逸
public StringBuffer createString(String ... values){
StringBuffer stringBuffer = new StringBuffer();
for (String string : values) {
stringBuffer.append(string+",");
}
return stringBuffer;
}
public static void main(String[] args) {
StringBuffer sb = new EscapeAnalysis().createString("Escape","Hello");
System.out.println(sb.toString());
}
(3)实例引用逃逸分析
比如将this给其他线程或者方法使用
(4)线程逃逸
赋值给类变量或可以在其他线程中访问的实例变量
-server JVM运行的模式之一, server模式才能进行逃逸分析, JVM运行的模式还有mix/client。
-XX:+DoEscapeAnalysis:启用逃逸分析(默认打开)
2.栈上分配
我们知道jvm中对象的创建都是在堆上,当对象没有被引用的时候,需要GC进行垃圾回收。如果对象数量太多的时候,会给GC带来较大压力,也会降低系统性能。为了降低临时对象创建带来的压力,如果对象没有逃逸,那就通过标量替换在栈上分配内存。这样对象内存就可以随栈针出栈而销毁,减少GC压力。
对栈上分配发生影响的参数就是三个,-server、-XX:+DoEscapeAnalysis和-XX:+EliminateAllocations,任何一个发生变化都不会发生栈上分配,因为启用逃逸分析和标量替换默认是打开的。
3.标量替换
标量就是不可再分解的量,JAVA的基本数据类型就是标量,反之就是聚合量,比如对象。如果逃逸分析确定对象不会被外部使用,并且可以再分。jvm不会创建该对象,而是将该对象成员变量分解若干个被这个方法使用的成员变量所代替。这些代替的成员变量在栈帧或寄存器上分配空间。
-XX:+EliminateAllocations:标量替换(默认打开)
4.同步消除
通过逃逸分析,可以确定一个对象是否被其他线程所使用。如果没有,而对象的方法上又有同步锁。jvm会消除对象的同步锁。
版权声明:本文为huanshirenjian原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。