6

When I say something like:

Thread t1 = new Thread();

does it create it on a heap or a stack?

4

3 回答 3

11

在 Java 中没有办法在栈上分配对象。
堆栈只能保存引用和原语,并且只能保存局部变量。

请注意,启动一个线程将为该线程创建一个新堆栈。

于 2013-10-17T17:39:43.943 回答
10
Thread t1 = new Thread();

tl;dr这会在堆中分配对象,即 t1。

随着每个新线程的出现,它都有自己的 pc 寄存器(程序计数器)和 Java 堆栈。如果线程正在执行 Java 方法(不是本地方法),则 pc 寄存器的值指示要执行的下一条指令。线程的 Java 堆栈存储线程的 Java(非本地)方法调用的状态。Java 方法调用的状态包括its local variables, the parameters with which it was invoked, its return value(如果有)and intermediate calculations、. 本机方法调用的状态以依赖于实现的方式存储在本机方法堆栈中,也可能存储在寄存器或其他依赖于实现的内存区域中。

Java 堆栈由堆栈帧(或帧)组成。堆栈帧包含一个 Java 方法调用的状态。当一个线程调用一个方法时,Java 虚拟机将一个新帧推送到该线程的 Java 堆栈上。当方法完成时,虚拟机弹出并丢弃该方法的帧。

Java 虚拟机没有寄存器来保存中间数据值。指令集使用 Java 堆栈来存储中间数据值。

该图显示了正在执行三个线程的虚拟机实例的快照。在快照的瞬间,线程一和二正在执行 Java 方法。线程三正在执行本机方法。它还显示了 Java 虚拟机为每个线程创建的内存区域,这些区域是所属线程的私有区域。没有线程可以访问另一个线程的 pc 寄存器或 Java 堆栈。

在此处输入图像描述

于 2013-10-17T18:03:54.703 回答
2

在 Java 8 中,使用 Escape Analysis 可以在堆栈上创建对象。当一个对象被检测为没有转义当前方法时会发生这种情况(在执行内联之后) 注意:这种优化在 Java 7 中可用,但我认为它效果不佳。

但是,一旦您调用start()它,它就会转义当前方法,因此它必须放在堆上。

当我说类似的话:

Thread t1 = new Thread();

它是在堆还是堆栈上创建它?

它可以将它放在堆栈上,前提是您不使用它来创建真正的线程。即如果你是这样

Thread t1 = new Thread(runnable);
t1.start();

它必须把它放在堆上。

于 2016-06-21T07:29:02.900 回答