对象逃逸分析&栈上内存分配

对象栈上分配

我们通过JVM内存分配可以知道JAVA中的对象都是在堆上进行分配,当对象没有被引用的时候,需要依靠GC进行回收内存,如果对象数量较多的时候,会给GC带来较大压力,也间接影响了应用的性能。为了减少临时对象在堆内分配的数量,JVM通过逃逸分析 确定该对象不会被外部访问。如果不会逃逸可以将该对象在栈上分配内存,这样该对象所占用的内存空间就可以随栈帧出栈而销毁,就减轻了垃圾回收的压力。

对象逃逸分析

就是分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中。

test1方法有返回值,返回值会的作用域范围不确定,那么就不能在栈上分配内存;而test2方法中的user对象作用域范围就是该方法,无外部引用,那么就可以在栈上分配内存,当方法结束时随方法一起被释放回收。

java 复制代码
public User test1() {
	User user = new User();
	user.setld(1);
	user. setName ("zhuge" );
	return user;
}

public void test2() {
	User user = new User);
	user.setid(1):
	user.setName ("zhuge");
}

那么,就相当于不是所有对象都是被分配在堆上的!!

标量替换

问题:在为对象分配内存时,一般是需要连续的内存空间;而栈帧的内存空间本就比较小,甚至可能不连续或者不能放下一整个对象,此时要为对象在栈上分配内存,该怎么办----> 标量替换

定义:把一个对象打散,将其成员变量分开放入栈帧的内存空间中,这些成员变量都会有标识能够标识出属于同一个对象,这就叫标量替换。

标量 :不可被进一步分解的量,java的基本数据类型(int long等基本数据类型以及reference)都是标量,与之相反的就是聚合量。

聚合量:可以进一步被分解的量,java对象就是可以被进一步分解的量。

参数配置

开启逃逸分析的参数:-XX:+DoEscapeAnalysis (这里有个小知识点:+代表开启;-代表关闭><),JDK7之后默认开启

开启标量替换的参数:-XX:+EliminateAllocations,JDK7之后默认开启

这两个参数要搭配使用(即,同时启用)才会有性能提升,才能减少GC.