逃逸分析----在计算机语言编译器语言优化管理中,分析指针动态范围的方法称之为逃逸分析(通俗点讲,当一个对象的指针被多个方法或线程引用时)---我们称这个指针发生了逃逸。
- public class G {
- public static B b;
- public void globalVariablePointerEscape(){//给全局变量赋值,发生逃逸
- b=new B();
- }
- public B methodPointerEscape(){//方法返回值,发生逃逸
- return new B();
- }
- public void instancePassPointerEscape(){
- methodPointerEscape().printClassName(this);//实例引用发生逃逸
- }
- }
- class B{
- public void printClassName(G g){
- System.out.println(g.getClass().getName());
- }
- }
在这个例子中,一共举了3种常见的指针逃逸场景。分别是 全局变量赋值,方法返回值,实例引用传递。
逃逸分析优化JVM原理
我们知道java对象是在堆里分配的,在调用栈中,只保存了对象的指针。
当对象不再使用后,需要依靠GC来遍历引用树并回收内存,如果对象数量较多,将给GC带来较大压力,也间接影响了应用的性能。减少临时对象在堆内分配的数量,无疑是最有效的优化方法。
怎么减少临时对象在堆内的分配数量呢?不可能不实例化对象吧!
场景介绍
其实,在java应用里普遍存在一种场景。一般是在方法体内,声明了一个局部变量,且该变量在方法执行生命周期内未发生逃逸(在方法体内,未将引用暴露给外面)。
按照JVM内存分配机制,首先会在堆里创建变量类的实例,然后将返回的对象指针压入调用栈,继续执行。
这是优化前,JVM的处理方式。
逃逸分析优化 - 栈上分配
优化原理:分析找到未逃逸的变量,将变量类的实例化内存直接在栈里分配(无需进入堆),分配完成后,继续在调用栈内执行,最后线程结束,栈空间被回收,局部变量对象也被回收。
这是优化后的处理方式,对比可以看出,主要区别在栈空间直接作为临时对象的存储介质。从而减少了临时对象在堆内的分配数量。
逃逸分析的原理很简单,但JVM在应用过程中,还是有诸多考虑。
比如,逃逸分析不能在静态编译时进行,必须在JIT里完成。原因是,与java的动态性有冲突。因为你可以在运行时,通过动态代理改变一个类的行为,此时,逃逸分析是无法得知类已经变化了。
逃逸分析另一个重要的优化 - 同步消除
如果你定义的类的方法上有同步锁,但在运行时,却只有一个线程在访问,此时逃逸分析后的机器码,会去掉同步锁运行。
性能测试
来自http://blog.uncommons.org/性能测试结果。
测试场景1:
生成几百万个随机数,然后做一些少量运算。
VM 参数: -server
95 秒
VM 参数: -server -XX:+DoEscapeAnalysis
73 秒
性能提高: 23%
测试场景2:
非负矩阵分解算法。
VM 参数: -server
22.6 秒
VM 参数: -server -XX:+DoEscapeAnalysis
20.8 秒
性能提升: 8%
JVM中启用逃逸分析 DoEscapeAnalysis
安装jdk1.6.0_14,运行java时传递jvm参数 -XX:+DoEscapeAnalysis
逃逸分析还能用于以下优化场景,但在JVM中未知使用。
1,标量替换(Scalar Replacement)
2,减小竞争检测范围
3,基于区域的内存分配
…...
参考资料:
http://www.cag.csail.mit.edu/~rinard/pointer_and_escape_analysis/
http://developer.amd.com/documentation/Articles/pages/01302008_jvm.aspx
http://en.wikipedia.org/wiki/Escape_analysis
http://en.wikipedia.org/wiki/Java_performance#Escape_analysis_and_lock_coarsening
http://staff.ustc.edu.cn/~yuzhang/papers/cncc07.pdf(一种实现方法,过于学术,不过引言部分写得很不错)
http://java.dzone.com/articles/escape-analysis-java-6-update
http://en.wikipedia.org/wiki/Non-negative_matrix_factorization
相关推荐
逃逸分析(Escape Analysis)是Java虚拟机中的一个重要优化技术,它通过对程序进行跨函数全局的数据流分析,判断一个新创建的对象是否会被外部方法或者外部线程访问。如果分析结果显示对象不会逃逸出当前作用域,JVM...
Sreedhar, Sam Midkiff 等在论文《Escape Analysis for Java》中描述的算法。该算法引入了连通图,用连通图来构建对象和对象引用之间的可达性关系,并在次基础上,提出一种组合数据流分析法。 5. 逃逸分析的处理...
JVM 逃逸分析(Escape Analysis)是一种可以有效减少 Java 程序中同步负载和内存堆分配压力的跨函数全局数据流分析算法。通过逃逸分析,Java Hotspot 编译器能够分析出一个新的对象的引用的使用范围,从而决定是否...
这种技术基于Jong-Deok Choi等人在1999年的论文《Escape Analysis for Java》中描述的算法。算法使用连通图来分析对象及其引用之间的可达性,通过上下文相关和流敏感的数据流分析,精确地判断对象的逃逸情况。虽然...
5. 编译器优化:编译器在编译Java代码时会进行各种优化,例如逃逸分析(Escape Analysis)是Java虚拟机(JVM)中的一个特性,用于决定对象的分配地点及生命周期。如果编译器能准确分析出引用不逃逸,则可以进行栈上...
在论文《Escape Analysis for Java》中描述的算法进行逃逸分析的。该算法引入了连通图,用连通图来构建对象和对象引用之间的可达性关系,并在次基础上,提出一种组合数据流分析法。 逃逸分析的结果可以得到三种...
在Java的实时编程中,还有一些关键特性,如逃逸分析(Escape Analysis)、标量替换(Scalar Replacement)、锁消除(Lock Elimination)和死代码消除(Dead Code Elimination)等。这些优化技术有助于减少内存分配、...
6. **逃逸分析(Escape Analysis)**: 逃逸分析是一种用于确定对象生命周期和分配方式的技术。如果分析发现对象不会逃出当前作用域,JVM可能会将对象分配在栈上,从而避免GC的开销。 7. **并发与多线程优化**: ...
此外,对于频繁创建和销毁的小对象,可以考虑使用栈上分配(Stack Allocation)或逃逸分析(Escape Analysis)来避免不必要的堆分配,提升性能。总之,深入理解JVM的工作原理是进行有效调优的前提。
这种方法被称为栈上复用(Stack Allocation)或逃逸分析(Escape Analysis)。 4. **优化决策**:根据分析结果,JVM可以做出其他优化决策,比如是否启用标量替换(Scalar Replacement),即将对象的字段拆分为独立的...
JDK 7引入了一些编译优化策略,比如逃逸分析(Escape Analysis),可以减少对象创建的开销,提高程序性能。 5. **多线程支持**: 在编译过程中,javac可能需要处理多线程问题,比如并行编译,这在源码中会有相应...
2. 编译器优化:Go的编译器会自动进行一些优化,例如逃逸分析(escape analysis),它可以决定变量是否需要分配到堆上,从而减少内存分配的开销。了解这些内部机制可以帮助我们在编写代码时更好地利用编译器的优势。...
3. **编译器优化**:如逃逸分析(Escape Analysis),帮助减少对象创建的开销,提高程序运行效率。 三、其他重要功能 1. **改进的日志框架**:JDK6引入了`java.util.logging`包,提供了一种轻量级的日志记录解决...
- **逃逸分析(Escape Analysis)**: 有助于减少无用对象的创建,提高程序效率。 - **类型推断(Type Inference)**: 在泛型使用中,编译器可以自动推断类型,使得代码更加简洁。 3. **Java虚拟机(JVM)改进**:...
为了确保闭包能够正确访问`i`,Go编译器进行了一种称为“逃逸分析”(Escape Analysis)的过程。 逃逸分析是Go编译器的一项技术,用于确定变量是否需要在堆上分配内存。在上面的`f`函数示例中,如果`c`是一个局部...
例如,加入了逃逸分析(Escape Analysis),该技术有助于减少对象分配和垃圾回收的开销。 3. **改进的内存管理**: 垃圾收集器(Garbage Collector)得到了显著提升,尤其是对于新生代和老年代的垃圾收集策略。...
锁粗化是逃逸分析技术(Escape Analysis)的一个应用,其目的是减少多线程中锁的竞争和同步开销。它通过合并相邻的几个锁定区域来实现这一点,从而减少锁定操作的频率。 锁粗化这一概念其实可以类比为编译器优化中...