Java中对象的逃逸分析
文章目录
- 逃逸分析的定义
- 对象的逃逸状态
- 1. 全局逃逸
- 2. 参数逃逸
- 3. 没有逃逸
- 小结
- 逃逸分析优化方式
- 1. 锁消除
- 2. 栈上分配
- 3. 标量替换
我们常说:在Java中,new出来的对象都是被分配在堆上,但是这个结论不是那么的绝对。
在Java SE 6u23版本之前,对象的创建都是在堆空间创建的。但在Java SE 6u23版本版本及之后,HotSpot中默认开启了逃逸分析,所以对象还可能存在栈上。
开启关闭逃逸分析:
执行java程序时,可以通过如下参数开启或者关闭"逃逸分析"
开启逃逸分析:-XX:+DoEscapeAnalysis
关闭逃逸分析:-XX:-DoEscapeAnalysis
逃逸分析的定义
逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。逃逸分析在Java即时编译器(JIT)编译Java源代码时使用。
通过逃逸分析算法可以分析出某一个方法中的某个对象是否会被其它方法或者线程访问到。如果分析结果显示某对象并不会被其它线程访问,则有可能在编译期间其做一些深层次的优化。
Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。
对象的逃逸状态
逃逸分析将对象分为三种逃逸状态:
- 全局逃逸(GlobalEscape)
- 参数逃逸(ArgEscape)
- 没有逃逸(NoEscape)
1. 全局逃逸
对象的作用范围逃出了当前方法或者当前线程,如:
- 对象是一个静态变量
- 对象作为方法的返回值
- 复写了finalize()方法的类,该类的的对象都会被标记为全局逃逸状态并且一定会放在堆内存中
2. 参数逃逸
对象被作为方法参数传递或者被参数引用,但在调用过程中不会再被其它方法或者线程访问。这个对象标记为参数级别的逃逸。
3. 没有逃逸
对象只在方法内部使用,没有发生逃逸。
对于没有逃逸的这种对象,Java即时编译器会做出进一步的优化。
小结
对象逃逸可以分为两种:方法逃逸、线程逃逸
方法逃逸:对象逃出当前方法
对象在方法里面被定义后,它可能被外部方法所引用,如:
- 对象作为方法的返回值或对象的引用包含在返回值中
- 对象作为方法参数传递或者被参数引用
线程逃逸:对象逃出当前线程
对象可能被其它线程访问到
- 对象是一个静态变量
- 对象是一个可以在其它线程中访问的实例变量
逃逸分析优化方式
- 如果对象的逃逸状态是全局逃逸或者参数逃逸,则此对象必须被分配在堆内存中;
- 但是如果对象的逃逸状态是没有逃逸状态,则不一定被分配在堆内存中。
具体逃逸分析的优化有下面几种方式。
1. 锁消除
如果对象不会逃逸,这个对象就永远不会被其它方法或者线程访问到。
这时对象锁synchronized(object) 没有任何意义(因为在任何线程中,object都是不同的锁对象)。所以JVM会对上述代码进行优化,删除锁。
锁消除举例:
public void lockEliminate() {User user = new User();synchronized (user) {System.out.println("执行同步代码块");}}
在lockEliminate() 方法中,对象user永远不会被其它方法或者线程访问到,因此user是不会逃逸对象,这就导致synchronized(user) 没有任何意义,因为在任何线程中,user都是不同的锁对象。
所以JVM会对上述代码进行优化,删除同步相关代码,如下:
public void lockEliminate() {User user = new User();System.out.println("执行同步代码块");}
常见的锁消除场景:StringBuffer
public void lockEliminate() {StringBuffer stringBuffer = new StringBuffer();stringBuffer.append("1");stringBuffer.append("2");System.out.println(stringBuffer.toString());}
此时append方法上的synchronized锁会被消除
@Overridepublic synchronized StringBuffer append(String str) {toStringCache = null;super.append(str);return this;}
实际等同于
@Overridepublic StringBuffer append(String str) {toStringCache = null;super.append(str);return this;}
2. 栈上分配
如果对象不会逃逸,那么这个对象可能会被分配在栈内存上而非常见的堆内存上(对象分配消除)。
对象分配消除:是指将本该在"堆"中分配的对象,转化为由"栈"中分配。
上面为什么说的是可能呢?
因为Hotspot中采用的是解释器和编译器并行的架构,所谓的混合模式就是解释器和编译器搭配使用。
- 当程序启动初期,采用解释器执行(同时会记录相关的数据,比如函数的调用次数,循环语句执行次数),节省编译的时间。
- 在使用解释器执行期间,记录的函数运行的数据,通过这些数据发现某些代码是热点代码,采用编译器对热点代码进行编译,以及优化(逃逸分析就是其中一种优化技术)。
所以逃逸分析只在编译器进行编译才会有。
3. 标量替换
如果对象不会逃逸,分配到栈内存的时候,会进行标量替换。
栈中直接分配对象难度太大,需要修改JVM中大量堆优先分配的代码,因此在HotSpot中并没有真正的实现栈中分配对象的功能,取而代之的是一个叫做标量替换的折中办法。
标量和聚合量:
- 标量:基础类型和对象的引用可以理解为标量,它们不能被进一步分解
- 聚合量:能被进一步分解的量就是聚合量,对象就是聚合量,它可以被进一步分解成标量
将对象的成员变量分解为分散的标量,这就叫做标量替换。
这样,如果一个对象没有发生逃逸,那压根就不需要在"堆"中创建它,只会在栈或者寄存器上创建一些能够映射这个对象标量即可,节省了内存空间,也提升了应用程序性能。
Java中对象的逃逸分析相关推荐
- java标量替换_JAVA逃逸分析、栈上分配、标量替换、同步消除
一.逃逸分析 逃逸分析是编译语言中的一种优化分析,而不是一种优化的手段.通过对象的作用范围的分析,为其他优化手段提供分析数据从而进行优化. 逃逸分析包括: 全局变量赋值逃逸 方法返回值逃逸 实例引用发 ...
- 浅析Java中对象的创建与对象的数据类型转换
这篇文章主要介绍了Java中对象的创建与对象的数据类型转换,是Java入门学习中的基础知识,需要的朋友可以参考下 Java:对象创建和初始化过程 1.Java中的数据类型 Java中有3个数据 ...
- [转载] java中对象作为参数传递给一个方法,到底是值传递,还是引用传递
参考链接: 用Java传递和返回对象 看完绝对清晰~ java中对象作为参数传递给一个方法,到底是值传递,还是引用传递? pdd:所谓java只有按值传递:基本类型 值传递:引用类型,地址值传递,所 ...
- java数组释放内存空间,Java中数组的内存分析
正文 引言: 墨白在文末给大家准备了程序员的适用壁纸,需要的小伙伴自取,今天的内容是给大家聊聊Java中数组的内存分析和原理,很多朋友可能已经忘记了,毕竟这是非常基础的点了,这次算是给大家复习了吧! ...
- Java 中对象占用内存大小计算
原文地址 mp.weixin.qq.com byte 与 bit bit:位,比特.信息的最小单位,二进制数中的一个位数 (二进制位),其值为"0" 或"1": ...
- Java中对象的储存区
文章目录 1 两个重要的问题 2 C语言中数据的存储区 3 Java中对象的储存区 4 Java为什么采用动态内存分配? 4 为什么基本类型是特例? 1 两个重要的问题 对象的数据位于何处? 如何控制 ...
- Java中对象的实例化顺序
文章目录 1 Java中对象的实例化顺序 1 Java中对象的实例化顺序 继承后的初始化顺序: 静态成员包括静态构造代码块,初始化顺序跟书写顺序有关.
- Java中对象的三种状态
转载自 Java中对象的三种状态 Java中的对象的三种状态是和垃圾回收紧密相关的,因此有必要深究. 状态一:可触及态:从根节点开始,可以搜索到这个对象,也就是可以访问到这个对象,也有人将其称为可 ...
- Java中对象和引用的理解
2019独角兽企业重金招聘Python工程师标准>>> 偶然想起Java中对象和引用的基本概念,为了加深下对此的理解和认识,特地整理一下相关的知识点,通过具体实例从两者的概念和区别两 ...
- java中的的一些生命周期,Java中对象的生命周期
Java中对象的生命周期 (1) 对象生命周期的开始 对象生命周期开始时,需要为对象分配内存,并且初始化它的实例变量: 对象生命周期结束 Java虚拟机的垃圾回收线程回收对象的内存. (2) 创建一个 ...
最新文章
- 【译】An Opinionated Introduction to AutoML and Neural Architecture Search
- 阿里云esc服务器和mysql_解决远程链接阿里云esc服务器的mysql数据库
- java 对话框 显示图片_Java对话框上显示图片
- ipsec_profile
- 获取计算机最大磁盘,Qt获取电脑磁盘容量(示例代码)
- mybatis Table book.t_abmin not find
- Silverlight 数据绑定(Binding)
- 数据结构与算法笔记——用Go语言描述
- T00LS专访白帽子:carry_your和带头大哥【T00ls人物专访第八期】
- 【JSP笔记02】JSP注释、脚本、表达式、JSP三大指令、JSP七大动作的介绍及使用
- 苏大与东大计算机软件专业比较,东北大学和苏州大学哪个实力更强一些?网友:苏大强?...
- WPF 方块按钮 仿照360
- 【对称日】今天朋友圈对称日刷屏了,也来凑个热闹,用代码实力打脸
- 乐高魔方机器人编程及图纸_魔方机器人教程图纸程序下载【Reinhard Grafl】作品...
- Gartner就超融合创新的角度专门作报告进行阐述-云宏超融合进入Gartner宣传
- 经典算法——韩信点兵问题的简单算法
- 绿盟科技技术大会 TechWorld 2016完美谢幕
- 小朱学英语------day 3 Ne zha's success and a blast from the past
- easyexcel 异常:java.lang.NoClassDefFoundError: org/apache/poi/poifs/filesystem/filemagic
- 设置win7系统时间