简述Java编程语言中的逃逸分析

所属分类: 软件编程 / java 阅读数: 22
收藏 0 赞 0 分享

        大家一般认为new出来的对象都是被分配在堆上,但这并不是完全正确,通过对Java对象分配过程分析,我们发现对象除了可以被分配在堆上,还可以在栈或TLAB中分配空间。而栈上分配对象的技术基础是逃逸分析和标量替换,本文主要介绍下逃逸分析。

1.逃逸分析的定义

        逃逸分析:是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。

        通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。

        Java在Java SE 6u23以及以后的版本中支持并默认开启了逃逸分析的选项。Java的 HotSpot JIT编译器,能够在方法重载或者动态加载代码的时候对代码进行逃逸分析。

        逃逸分析的基本行为就是分析对象的动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用。

        方法逃逸:例如作为调用参数传递到其他方法中。

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

2.逃逸分析的理论基础

        基于 Jong-Deok Choi, Manish Gupta, Mauricio Seffano,Vugranam C. Sreedhar, Sam Midkiff等在论文《Escape Analysis for Java》中描述的算法进行逃逸分析。

        该算法引入了连通图,用连通图来构建对象和对象引用之间的可达性关系,并在次基础上,提出一种组合数据流分析法。由于该算法是上下文相关和流敏感的,并且模拟了对象任意层次的嵌套关系,所以分析精度较高,只是运行时间和内存消耗相对较大。

        绝大多数逃逸分析的实现都基于“封闭世界(closed world)”的前提:所有可能被执行的,方法在做逃逸分析前都已经得知,并且,程序的实际运行不会改变它们之间的调用关系 。但当真实的 Java 程序运行时,这样的假设并不成立。Java 程序拥有的许多特性,例如动态类加载、调用本地函数以及反射程序调用等等,都将打破所谓“封闭世界”的约定。

逃逸分析之后的处理操作

        经过逃逸分析之后,可以得到对象三种可能的逃逸状态
        GlobalEscape(全局逃逸): 即一个对象的引用逃出了方法或者线程。例如,一个对象的引用是复制给了一个类变量,或者存储在在一个已经逃逸的对象当中,或者这个对象的引用作为方法的返回值返回给了调用方法。

        ArgEscape(参数级逃逸):即在方法调用过程当中传递对象的应用给一个方法。这种状态可以通过分析被调方法的二进制代码确定。

        NoEscape(没有逃逸):一个可以进行标量替换的对象。该对象可以不被分配在传统的堆上。

        编译器可以使用逃逸分析的结果,对程序进行优化。

        堆分配对象变成栈分配对象:一个方法当中的对象,对象的引用没有发生逃逸,那么这个方法可能会被分配在栈内存上而非常见的堆内存上。

        消除同步:线程同步的代价是相当高的,同步的后果是降低并发性和性能。逃逸分析可以判断出某个对象是否始终只被一个线程访问,如果只被一个线程访问,那么对该对象的同步操作就可以转化成没有同步保护的操作,这样就能大大提高并发程度和性能。

        矢量替代:逃逸分析方法如果发现对象的内存存储结构不需要连续进行的话,就可以将对象的部分甚至全部都保存在CPU寄存器内,这样能大大提高访问速度。

以上是本文关于逃逸分析的全部内容,希望对大家有所帮助。

更多精彩内容其他人还在看

Java的面向对象编程基本概念学习笔记整理

这篇文章主要介绍了Java的面向对象编程基本概念学习笔记整理,包括类与方法以及多态等支持面向对象语言中的重要特点,需要的朋友可以参考下
收藏 0 赞 0 分享

Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法

这篇文章主要介绍了Eclipse下编写java程序突然不会自动生成R.java文件和包的解决办法 的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

基于Java实现杨辉三角 LeetCode Pascal's Triangle

这篇文章主要介绍了基于Java实现杨辉三角 LeetCode Pascal's Triangle的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java中Spring获取bean方法小结

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架,如何在程序中获取Spring配置的bean呢?下面通过本文给大家介绍Java中Spring获取bean方法小结,对spring获取bean方法相关知识感兴趣的朋友一起学习吧
收藏 0 赞 0 分享

如何计算Java对象占用了多少空间?

在Java中没有sizeof运算符,所以没办法知道一个对象到底占用了多大的空间,但是在分配对象的时候会有一些基本的规则,我们根据这些规则大致能判断出来对象大小,需要的朋友可以参考下
收藏 0 赞 0 分享

剖析Java中的事件处理与异常处理机制

这篇文章主要介绍了Java中的事件处理与异常处理机制,讲解Java是如何对事件或者异常作出响应以及定义异常的一些方法,需要的朋友可以参考下
收藏 0 赞 0 分享

详解Java的Struts2框架的结构及其数据转移方式

这篇文章主要介绍了详解Java的Struts2框架的结构及其数据转移方式,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

Java封装好的mail包发送电子邮件的类

本文给大家分享了2个java封装好的mail包发送电子邮件的类,并附上使用方法,小伙伴们可以根据自己的需求自由选择。
收藏 0 赞 0 分享

在Java的Struts中判断是否调用AJAX及用拦截器对其优化

这篇文章主要介绍了在Java的Struts中判断是否调用AJAX及用拦截器对其优化的方法,Struts框架是Java的SSH三大web开发框架之一,需要的朋友可以参考下
收藏 0 赞 0 分享

java多线程Future和Callable类示例分享

JAVA多线程实现方式主要有三种:继承Thread类、实现Runnable接口、使用ExecutorService、Callable、Future实现有返回结果的多线程。其中前两种方式线程执行完后都没有返回值,只有最后一种是带返回值的。今天我们就来研究下Future和Callab
收藏 0 赞 0 分享
查看更多