逃逸分析(Escape Analysis)是目前Java虚拟机中比较前沿的优化技术。

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

例如:

StringBuffer sb是一个方法内部变量,上述代码中直接将sb返回,这样这个StringBuffer有可能被其他方法所改变,这样它的作用域就不只是在方法内部,虽然它是一个局部变量,称其逃逸到了方法外部。

甚至还有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量,称为线程逃逸。

上述代码如果想要StringBuffer sb不逃出方法,可以这样写:

不直接返回StringBuffer,那么StringBuffer将不会逃逸出方法。

如果能证明一个对象不会逃逸到方法或线程外,则可能为这个变量进行一些高效的优化。

1. 栈上分配

我们都知道Java中的对象都是在堆上分配的,而垃圾回收机制会回收堆中不再使用的对象,但是筛选可回收对象,回收对象还有整理内存都需要消耗时间。如果能够通过逃逸分析确定某些对象不会逃出方法之外,那就可以让这个对象在栈上分配内存,这样该对象所占用的内存空间就可以随栈帧出栈而销毁,就减轻了垃圾回收的压力。

在一般应用中,如果不会逃逸的局部对象所占的比例很大,如果能使用栈上分配,那大量的对象就会随着方法的结束而自动销毁了。

2. 同步消除

线程同步本身比较耗时,如果确定一个变量不会逃逸出线程,无法被其它线程访问到,那这个变量的读写就不会存在竞争,对这个变量的同步措施可以清除。

3. 标量替换

Java虚拟机中的原始数据类型(int,long等数值类型以及reference类型等)都不能再进一步分解,它们就可以称为标量。相对的,如果一个数据可以继续分解,那它称为聚合量,Java中最典型的聚合量是对象。如果逃逸分析证明一个对象不会被外部访问,并且这个对象是可分解的,那程序真正执行的时候将可能不创建这个对象,而改为直接创建它的若干个被这个方法使用到的成员变量来代替。拆散后的变量便可以被单独分析与优化,可以各自分别在栈帧或寄存器上分配空间,原本的对象就无需整体分配空间了。

4. 总结

虽然概念上的JVM总是在Java堆上为对象分配空间,但并不是说完全依照概念的描述去实现;只要最后实现处理的“可见效果”与概念中描述的一直就没问题了。所以说,“you can cheat as long as you don't get caught”。Java对象在实际的JVM实现中可能在GC堆上分配空间,也可能在栈上分配空间,也可能完全就消失了。这种行为从Java源码中看不出来,也无法显式指定,只是聪明的JVM自动做的优化而已。

但是逃逸分析会有时间消耗,所以性能未必提升多少,并且由于逃逸分析比较耗时,目前的实现都是采用不那么准确但是时间压力相对较小的算法来完成逃逸分析,这就可能导致效果不稳定,要慎用。

由于HotSpot虚拟机目前的实现方法导致栈上分配实现起来比较复杂,因为在HotSpot中暂时还没有做这项优化。

Reference:Java的reference等于C的指针。所以,在Java的方法调用中,reference也要复制一份压入堆栈。在方法中对reference的操作就是对这个reference副本的操作。

相关JVM参数

-XX:+DoEscapeAnalysis 开启逃逸分析

-XX:+PrintEscapeAnalysis 开启逃逸分析后,可通过此参数查看分析结果。

-XX:+EliminateAllocations 开启标量替换

-XX:+EliminateLocks 开启同步消除

-XX:+PrintEliminateAllocations 开启标量替换后,查看标量替换情况。

java对象 内存逃逸_JVM内存逃逸相关推荐

  1. java 句柄池_深入理解JVM之Java对象的创建、内存布局、访问定位详解

    本文实例讲述了深入理解JVM之Java对象的创建.内存布局.访问定位.分享给大家供大家参考,具体如下: 对象的创建 一个简单的创建对象语句Clazz instance = new Clazz();包含 ...

  2. Java对象运行时在内存中的情况

    Java对象运行时在内存中的情况 您可能已经知道,一旦创建了一个对象,它就只是堆中的一系列字节.您可能对Java对象在内存中的情况感到好奇吗? 1.变量 以下是"Base"(B)类 ...

  3. java 对象压缩_理解Java对象:要从内存布局及底层机制说起,话说....

    前言 大家好,又见面了,今天是JVM专题的第二篇文章,在上一篇文章中我们说了Java的类和对象在JVM中的存储方式,并使用HSDB进行佐证,没有看过上一篇文章的小伙伴可以点这里:< 这篇文章主要 ...

  4. 快速带你分清java内存结构,java内存模型,java对象模型和jvm内存结构!

    现如今你是否有这样的感觉,无论生活还是学习,节奏都是非常的快,每天面对海量的知识信息,自己感觉都要hold不住了,每天打开微信公众号,是不是发现有几十条未读,无论是技术文章还是其他类型的文章,我们大多 ...

  5. 3704对象关闭时_JVM 通过逃逸分析就能让对象在栈上分配?没那么简单!

    本文转载自公众号 星哥笔记 作者:Danny姜 校对:承香墨影 经常会有面试官会问一个问题:Java 中的对象都是在"堆"中创建吗? 然后跟求职者大谈特谈「逃逸分析」,说通过「逃逸 ...

  6. 理解Java对象:要从内存布局及底层机制说起,话说....

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 前言 大家好,又见面了,今天是JVM专题的第二篇文章,在上 ...

  7. Java对象的创建、内存布局和访问定位

    在Java运行时数据区中,我们知道了虚拟机内存的概况,本文介绍虚拟机内存中的数据的其它细节,如对象如何创建.如何布局以及如何访问. 基于实用的原则,这里以HotSpot虚拟机和常用的内存区域Java堆 ...

  8. JAVA对象在JVM中内存分配

    如果你还不了解JVM内存模型的建议您先看下JVM内存模型 以一下代码为例,来分析下,java对象在内存中的空间分配. public class Student {private String name ...

  9. java 内存溢出 内存泄露_JVM——内存泄漏与内存溢出

    1.内存溢出 1.1 什么是Java的内存溢出? 在Java程序运行的过程中,经常会碰到以下错误:java.lang.OutOfMemoryError. 通俗讲,内存溢出是指程序在申请内存时,没有足够 ...

  10. java 堆内存分析_JVM内存堆布局图解分析

    JAVA能够实现跨平台的一个根本原因,是定义了class文件的格式标准,凡是实现该标准的JVM都能够加载并解释该class文件,据此也可以知道,为啥Java语言的执行速度比C/C++语言执行的速度要慢 ...

最新文章

  1. 如何运用下载来的模板
  2. 【论文浅析】Semi-supervised sequence tagging with bidirectional lm
  3. Windows7下如何设置MyEclipse2014字体大小
  4. asterisk1.8 账号信息mysql存储(动态)
  5. 查找空目录Linux,Linux中find批量删除空文件及空文件夹脚本
  6. php识别字符编码,PHP自动识别字符集编码并完成转码_PHP教程
  7. JavaScript学习笔记:语句
  8. vs2017项目配置
  9. html textbox控制内容,textbox只能输入数字
  10. t9.php,TPHP框架
  11. 艾伯维与和铂医药合作开发新冠病毒抗体;欧莱雅发起中国首个美妆科技初创挑战赛 | 美通企业日报...
  12. 网页链接在线提取工具-免费网页链接在线提取软件
  13. java 以2为底的对数_Java对数函数及Java对数运算
  14. OpenGL(十三) Alpha测试、剪裁测试
  15. 利用人性做大闸蟹,给予客户特殊的身份优越感,思维决定财富!
  16. 封装HDLC协议实现两个路由器互相通信
  17. golang学习(一)—— 简介
  18. ROS-3DSLAM(16):视觉部分visual estimator第九节 factor4
  19. 查看linux [Fedora] 系统信息
  20. 如何通过ps把彩色照片转换为黑白素描

热门文章

  1. springboot大学生就业规划系统毕业设计-附源码191451
  2. Java鸿鹄_(五)Java版Spring Cloud B2B2C o2o鸿鹄云商平台--技术框架3
  3. SD卡数据读取(fat文件模式)
  4. 袁帅做了两件意义非凡的事
  5. (第六章)hive之查询
  6. mysql当前时间相减_mysql 查询当前时间加减时间
  7. [Jzoj]3457. 沙耶的玩偶
  8. 对堆区、栈区、全局静态区的理解
  9. sh: warning: setlocale: LC_ALL: cannot change locale (zh_CN.GB18030)
  10. 数据挖掘思维和实战11 朴素贝叶斯:算一算你是否要买延误险