JVM的逃逸技术介绍

来源:互联网 发布:sql查询去除重复 编辑:程序博客网 时间:2024/05/21 07:14

在Java中每一个对象都有一定的作用域,理论上,一个对象在一块代码中构造,那么也应该在这块代码中被回收,但是实际上,我们经常会让一个对象存活更长的时间,超过定义它的代码块,这就好比一个人逃出了生他养他的地方,我们将这种现象称为逃逸。

JVM的逃逸技术介绍

逃逸

逃逸按照行为不同有可以分为方法逃逸和线程逃逸。方法逃逸是指在某一个方法中构造的对象,在该方法外部可以继续访问这个对象。产生方法逃逸一般是由于返回值返回,或者是将对象的引用设置到传入的参数中,如下图展示了两种产生方法逃逸的例子。

JVM的逃逸技术介绍

方法逃逸

线程逃逸则是在一个线程中构造的对象,能够在另一个线程中使用。这种情况是由于同一个对象被多个线程使用,产生资源占用而导致。下图就是一个通过共享静态变量,来实现线程逃逸的例子,这个例子中的resource对象在多线程的环境下会产生线程逃逸。

JVM的逃逸技术介绍

线程逃逸

至此,我们了解了如何判断一个对象是否会产生逃逸,那么对象逃逸有什么用呢?如果我们能够明确肯定一个对象不会产生逃逸,那么就可以对其进行很多的优化。下面本文就来介绍一下,Java虚拟机在确定对象不发生逃逸的情况下,所进行的一些高效的优化。

  1. 栈上分配

    众所周知,Java中对象时分配在堆上的,在初始化时,会在堆上分配一块空间,当这个对象不再使用时,会在之后发生垃圾回收时被回收,这是一个Java对象正常的生命周期。但是当能够明确对象不会发生逃逸时,就可以对这个对象做一个优化,不将其分配到堆上,而是直接分配到栈上,这样在方法结束时,这个对象就会随着方法的出栈而销毁,这样就可以将少垃圾回收的压力。

  2. 同步消除

    在多线程中,对于一个变量操作进行同步操作是效率很低的,当我们确定一个对象不会发生逃逸时,那么就没有必要对这个对象进行同步操作,所以如果代码中有对这种变量操作的同步操作,JVM将会取消同步,从而提升性能。

  3. 标量替换

    标量指的是没有办法再分解为更小的数据的类型,即Java中的基本类型,我们平时定义的类都属于聚合量。标量替换即是将一个聚合量拆成多个标量来替换,即用一些基本类型来代替一个对象。如果明确对象不会发生逃逸,并且可以进行标量替换的话,那么就可以不创建这个对象,而是直接使用基本类型来代替,这样也就可以节省创建和销毁对象的开销。

虽然基于逃逸技术的优化能够提升程序运行时的性能,但是在实际生产中,对象逃逸的分析默认是不开启的。这是因为分析一个对象是否会发生逃逸消耗比较大,所以,开启逃逸分析并进行这些优化之后得到的效果,并不一定就比不进行优化更好。如果确定开启逃逸分析效率更好,那么可以使用参数-XX:+DoEscapeAnalysis来开启逃逸分析。

本文为头条号作者发布,不代表今日头条立场。

0 0