Java 内存逃逸分析

对象分配

Java对象一定是在堆上分配的吗?
绝大多数的对象是在堆上分配的,但是也有例外。随着JIT即时编译器的出现,内存逃逸分析愈发成熟,栈上分配,标量替换,锁消除等优化技术也慢慢发展起来。
Java是通过javac编译成字节码,然后类加载器将该字节码文件加载到内存,逐行解析并翻译成机器码执行,因此解释执行会稍微慢一点。
而JIT会将频繁运行的代码定义为热点代码,将之编译成机器指令,加快运行。
内存逃逸分析是JIT重要的优化技术。

定义

一个对象是否会逃逸,主要看一个对象在一个方法内定义,是否有可能被外部引用了。
如:

public Test use(){
	Test test = new Test();
	return test;
}

这种情况下,会发生逃逸。
方法逃逸:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中
线程逃逸:甚至该对象还可能被外部线程访问到,例如赋值被类变量或可以在其他线程中访问的实例变量

进行内存逃逸分析的目的是为了进一步优化程序。
主要从:

  1. 栈上分配
  2. 标量替换
  3. 锁消除

栈上分配

如果一个对象没有发生内存逃逸,那该对象是有可能在栈上进行分配的,而不用分配到堆上,减少GC。
由于复杂度等原因,HotSpot中目前暂时还没有做这项优化,但一些其他的虚拟机(如Excelsior JET)使用了该优化

标量替换

如果一个对象没有发生内存逃逸,那么就有可能将该对象分解成若干个标量来代替。
标量替换可视为栈上分配一种特例,实现更简单(不用考虑对象完整结构的分配),但对逃逸程度的要求更高,它不允许对象逃逸出方法范围内。

public void replace() {
  Test test= new Test (1, 2);
  System.out.println(test.a);
  System.out.println(test.b);
}
————————————————
```java
public void replace() {
  Test test= new Test (1, 2);
  System.out.println(1);
  System.out.println(2);
}

在虚拟机中,并没有真正的实现栈上分配,本质上都是通过标量替换来实现

锁消除

如果一个对象没有发生内存逃逸,只能当前线程访问到,那么可能会进行优化锁消除。

开启

从Java1.7开始就默认开启了内存逃逸分析。
# 开启
-XX:+DoEscapeAnalysis
# 关闭
-XX:-DoEscapeAnalysis

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值