JVM内存增强之逃逸分析
作者:loading_... 发布时间:2022-01-23 00:22:08
概念
逃逸分析一种数据分析算法,基于此算法可以有效减少 Java 对象在堆内存中的分配。 Hotspot 虚拟机的编译器能够分析出一个新对象的引用范围,然后决定是否要将这个对象分配到堆上.
当一个对象在方法中被定义后,对象只在方法内部使用,则认为没有发生逃逸。
当一个对象在方法中被定义后,它被外部方法所引用,则认为发生逃逸。
//对象发生了逃逸,不会在栈上分配,有可能导致GC STW
public StringBuffer append(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb;
}
//对象未发生逃逸
public String append(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
建议:开发中能在方法内部应用对象的,就尽量控制在内部
逃逸分析参数设计
在 JDK 1.7 版本之后, HotSpot 中默认就已经开启了逃逸分析,如果使用的是较早的
版本,开发人员则可以通过:
✓ 选项“ -XX:+DoEscapeAnalysis" 显式开启逃逸分析。
✓ 通过选项“ -XX:+PrintEscapeAnalysis" 查看逃逸分析的筛选结果。
使用逃逸分析
编译器可以对代码做如下优化
1.栈上分配:将堆分配转化为栈分配。如果一个对象在方法内创建,要使指向该对象的引用不会发生逃逸,对象可能是栈上分配的候选
/**
* 栈上分配测试(-XX:+DoEscapeAnalysis)
* -Xmx128m -Xms128m -XX:+DoEscapeAnalysis -XX:+PrintGC
*/
public class ObjectStackAllocationTests {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
alloc();
}
long end = System.currentTimeMillis();
System.out.println("花费的时间为: " + (end - start) + " ms");
// 为了方便查看堆内存中对象个数,线程 sleep
TimeUnit.MINUTES.sleep(5);
}
private static void alloc() {
byte[] data = new byte[10];//未发生逃逸
}
}
2.同步锁消除:
我们知道线程同步是靠牺牲性能来保证数据的正确性,这个过程的代价会非常高。程序 的并发行和性能都会降低。JVM 的 JIT 编译器可以借助逃逸分析来判断同步块所使用的锁对象是否只能够被一个线程应用?假如是,那么 JIT 编译器在编译这个同步块的时候就会取消对这部分代码上加的锁。这个取消同步的过程就叫同步省略,也叫锁消除
public class SynchronizedLockTest {
public void lock() {
Object obj= new Object();
synchronized(obj) {
System.out.println(obj);
}
}
3.标量替换分析
所谓的标量(scalar)一般指的是一个无法再分解成更小数据的数据。例如,Java 中 的原始数据类型就是标量。相对的,那些还可以分解的数据叫做聚合量(Aggregate),Java 中的对象就是聚合量,因为他可以分解成其他聚合量和标量。在 JIT 阶段,如果经过逃逸分析,发现一个对象不会被外界访问的话,那么经过 JIT 优化,就会把这个对象分解成若干个变量来代替。这个过程就是标量替换。
public class ObjectScalarReplaceTests {
public static void main(String args[]) {
long start = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
alloc();
}
long end = System.currentTimeMillis();
System.out.println("花费的时间为: " + (end - start) + " ms");
}
private static void alloc() {
Point point = new Point(1,2);
}
static class Point {
private int x;
private int y;
public Point(int x,int y){
this.x=x;
this.y=y;
}
}
//对于上面代码,假如开启了标量替换,那么 alloc 方法的内容就会变为如下形式
private static void alloc() {
int x=10;
int y=20;
}
alloc 方法内部的 Point 对象是一个聚合量,这个聚合量经过逃逸分析后,发现他并没有逃逸,就被替换成两个标量了。那么标量替换有什么好处呢?可以大大减少堆内存的占用。因为一旦不需要创建对象了,那么就不再需要分配堆内存了。标量替换为栈上分配 提供了很好的基础。
FAQ
1.什么是逃逸分析?
可以有效减少 Java 对象在堆内存中的分配压力和同步负载的算法
2.逃逸分析有什么优势、劣势?
逃逸分析是需要消耗一定的性能去执行分析的,所以说如果方法中的对象全都是处于逃逸状态,那么就没有起到优化的作用,从而就白白损失了这部分的性能消耗
来源:https://blog.csdn.net/gtxy_2015/article/details/126902967


猜你喜欢
- 本文实例讲述了C#实现3步手动建DataGridView的方法。分享给大家供大家参考。具体如下:DataView dvCmControlIn
- MyBatis使用RowBounds实现的分页是逻辑分页,也就是先把数据记录全部查询出来,然在再根据offset和limit截断
- 为了打造流畅的用户导航体验,我们不得不依赖智能手机最常见的一个功能:触摸。触摸改变应用程序的视图是现在最流行一种导航设计。在本文中,我们将经
- 本文同时讨论了IComparable和IComparer接口,原因有两点。这两个接口经常一起使用。虽然接口类似且名称相似,但它们却有不同的用
- 前言Jetpack Compose(简称 Compose )是 Google 官方推出的基于 Kotlin 语言的 Android 新一代
- 方法一:需要调用win32api,winform、wpf通用[DllImport("user32.dll")]publi
- 获取整个屏幕的宽度的实例Point p = new Point();//获取窗口管理器WindowManager wm = (WindowM
- 一、简介正则表达式是一种匹配输入文本的模式,.Net 框架提供了允许这种匹配的正则表达式引擎,模式由一个或多个字符、运算符和结构组成。下面列
- Unity中的PostProcessBuild:深入解析与实用案例在Unity游戏开发中,我们经常需要在构建完成后对生成的应用程序进行一些额
- 本文实例讲述了C#实现利用泛型将DataSet转为Model的方法。分享给大家供大家参考。具体如下:因为网站需要用C#开发,习惯了java的
- Hystrix 是一个帮助解决分布式系统交互时超时处理和容错的类库, 它同样拥有保护系统的能力。Netflix的众多开源项目之一。设计流程:
- 引入字体首先在项目中创建fonts目录,然后将将ttf文件放到该目录下,然后在pubspec文件中添加该字体文件,如:...flutter:
- 目录1.加载本地Word2.以只读模式加载Word3.从流加载Word【程序环境】Windows 10Visual Studio 2017W
- 在Android开发中,定时器一般有以下3种实现方法:一、采用Handler与线程的sleep(long)方法二、采用Handler的pos
- 在Android实现没有标题栏的方法有两种:在代码中添加requestWindowFeature(Window.FEATURE_NO_TIT
- 新配置一个spring的MVC项目,发现对Get请求的中文参数出现了乱码:查看了SpingMVC中关于编码的配置(在web.xml中),如下
- 前文简单介绍了Android中SurfaceView的基本使用,本文就来介绍一下SurfaceView与多线程的混搭。SurfaceView
- Flyway的使用环境:SpringBoot 2.0.4.RELEASE为什么要用Flyway?开发人员在合作的时候经常遇到以下场景:1.开
- Mybatis映射文件mapper.xml的注释问题从昨天夜晚9点到今天中午,一直被项目bug所困惑,中间这段时间一直未解决这个问题,也咨询
- 前言Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据