从学习Java开始就写在前面,我们已经接触到这种观点:Java对象是在堆上创建的,对象引用是在堆栈上放置的,那么这种观点真的正确吗?如果是正确的,那么访问者为什么要问:“是否必须在堆中分配Java中的对象?”那这个问题呢?似乎我们从Java中灌输的观点值得怀疑。

关于采访问题标题中的采访问题是:Java对象和数组是否分配在堆上?当面试官问这个问题时,一些朋友会心中想:我从学习Java开始就知道:Java对象是在堆上创建的,对对象的引用存储在堆栈上,因此Java中的对象和数组必须被分配在堆上!是不是?如果您这样回答,您将直接被假冒。

也许有些朋友仍然不了解,然后让我们继续看不起。

采访问题的答案首先,让我们给出这个问题的答案。

在这里,我将简要回答这个采访问题,稍后我们将进行相关分析。

您可以回答:Java中的对象不一定要在堆上分配,因为JVM可以通过转义分析来分析新对象的使用范围,并确定是否将此对象分配给堆。

如果JVM发现某些对象没有转义方法,则很可能会将它们优化为分配在堆栈上。

在这里,我们面临一个新术语:逃逸分析。

我相信许多朋友不太了解,所以让我们继续看不起。

逃逸分析逃逸分析的概念首先要讨论什么是正式形式的逃逸分析。

转义分析是:一种静态分析,用于确定指针的动态范围,它可以分析可以在程序中访问指针的位置。

在JVM即时编译的情况下,转义分析将确定新创建的对象是否转义。

即时编译判断对象是否转义:一个是对象是否存储在堆中(对象的静态字段或实例字段在堆中),另一个是对象是否传递给未知代码。

直接说这些概念,确实有些令人头晕,所以让我们举两个例子。

对象转义的示例典型的对象转义是:将对象复制到成员变量或静态变量,并且可以在外部使用,此时,该变量转义。

我们可以使用以下代码来表示这种现象。

/ *** @author binghe * @description对象转义示例1 * //公共类ObjectEscape {private User user; public void init(){user = new User();在ObjectEscape类中,有一个成员变量user,在init()方法中,我们创建了User类的对象,并将其分配给成员变量user。

此时,对象被复制到成员变量,并且可以在外部使用,并且此时的变量将转义。

另一个典型的情况是:通过return语句返回对象。

如果对象是通过return语句返回的,则此时程序不确定该对象是否将来会被使用,外部线程可以访问此变量,并且该对象此时将转义。

我们可以使用以下代码来表示这种现象。

/ *** @author binghe * @description对象转义示例2 * //公共类ObjectReturn {public User createUser(){User user = new User();返回用户;返回用户;举两个例子,我相信我的朋友是对JVM转义分析有所了解,是的,JVM可以通过转义分析来分析新对象的使用范围,从而确定是否应在堆上分配新对象。

我们还没有结束,让我们继续研究转义分析的优势,以便朋友可以更好地理解转义分析。

转义分析的优点转义分析的优点通常可以分为三部分:可以在堆栈上分配对象,可以用标量分隔或替换对象,并且可以消除同步锁。

我们可以用下图来表示。

可以在堆栈上分配对象。

通过转义分析,JVM分析了新对象的使用范围,然后可以在堆栈上分配该对象。

堆栈分配可以快速在堆栈框架上创建和销毁对象,而不必将对象分配到堆空间,这可以有效地减轻JVM垃圾回收的压力。

对象分离或标量替换。

当JVM通过转义分析确定要将该对象分配给堆栈时,即时编译可以分解该对象,并用较小的局部变量替换该对象。

我们称此为破坏标量替换的过程。

用局部变量替换对象后,它