大家一般认为new出来的对象都是被分配在堆上,但这并不是完全正确,通过对Java对象分配过程分析,我们发现对象除了可以被分配在堆上,还可以在栈或TLAB中分配空间。而栈上分配对象的技术基础是逃逸分析和标量替换,本文主要介绍下逃逸分析。
逃逸分析的定义
逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。
通过逃逸分析,Java Hotspot编译器能够分析出一个新的对象的引用的使用范围从而决定是否要将这个对象分配到堆上。
Java在Java SE 6u23以及以后的版本中支持并默认开启了逃逸分析的选项。Java的 HotSpot JIT编译器,能够在方法重载或者动态加载代码的时候对代码进行逃逸分析。
逃逸分析的基本行为就是分析对象的动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用。
方法逃逸:例如作为调用参数传递到其他方法中。
线程逃逸:有可能被外部线程访问到,譬如赋值给类变量或可以在其他线程中访问的实例变量。
逃逸分析的理论基础
基于 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中jvm逃逸问题分析,包括了java中jvm逃逸问题分析的使用技巧和注意事项,需要的朋友参考一下 引言: 逃逸分析(Escape Analysis)是众多JVM技术中的一个使用不多的技术点,本文将通过一个实例来分析其使用场景。 概念 逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot编译器能够
本文向大家介绍面试中遇到的java逃逸分析问题,包括了面试中遇到的java逃逸分析问题的使用技巧和注意事项,需要的朋友参考一下 前言 记得几年前有一次栈长去面试,问到了这么一个问题: Java中的对象都是在堆中分配吗?说明为什么! 当时我被问得一脸蒙逼,瞬间被秒杀得体无完肤,当时我压根就不知道他在考什么知识点,难道对象不是在堆中分配吗?最后就没然后了,回去等通知了。。 下面我收集了一下网友的回答。
本文向大家介绍Java并发编程this逃逸问题总结,包括了Java并发编程this逃逸问题总结的使用技巧和注意事项,需要的朋友参考一下 this逃逸是指在构造函数返回之前其他线程就持有该对象的引用. 调用尚未构造完全的对象的方法可能引发令人疑惑的错误, 因此应该避免this逃逸的发生. this逃逸经常发生在构造函数中启动线程或注册监听器时, 如: 解决办法 以上就是小编本次整理的全部内容,感谢你
我正在使用terraform文件中的remote exec provisioner在ec2上运行一些命令。但我一直在逃避命令中的特殊字符。这部分代码来自我的main。远程exec provisioner部分中的tf文件。terraform中出现的错误是“无效字符”和“无效多行字符串”。我想要正确的字符串序列,以便这些命令可以在我的ec2上执行。
我已通过设置以下内容将PowerShell添加到上下文菜单: 这工作得很好,除了我出色地命名为的文件夹。它失败了: 从文档: 指定位置的路径。LiteralPath参数的值的使用方式与键入的完全相同。没有字符被解释为通配符。如果路径包含转义字符,请用单引号将其括起来。单引号告诉PowerShell不要将任何字符解释为转义序列。 我是否可以选择使用,希望我的目录名称中没有可能的通配符?或者可以在中转
我想把JavaScript onClick属性使用Thym立叶。 我这样写代码 此代码正在运行。当productName包含这样的特殊字符时,我会遇到问题 然后JavaScript函数看起来像这样 我需要从产品名称中转义双引号和单引号字符。我该怎么做?