【发布时间】:2013-10-26 08:16:15
【问题描述】:
当我说这样的话:
Thread t1 = new Thread();
它是在堆还是栈上创建它?
【问题讨论】:
-
“可见”部分在 JVM 堆中。对于正在运行的线程,至少还有一个特定于操作系统的部分被分配到其他地方,但它都是自动处理的。
标签: java multithreading concurrency
当我说这样的话:
Thread t1 = new Thread();
它是在堆还是栈上创建它?
【问题讨论】:
标签: java multithreading concurrency
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 堆栈。
【讨论】:
在 Java 8 中,使用 Escape Analysis 可以在堆栈上创建对象。当检测到对象未转义当前方法时会发生这种情况(在执行内联之后)注意:此优化在 Java 7 中可用,但我认为效果不佳。
但是,一旦您调用start(),它就会转义当前方法,因此必须将其放在堆上。
当我说这样的话:
Thread t1 = new Thread();它是在堆还是栈上创建它?
它可以将它放在堆栈上,前提是您不使用它来创建真正的线程。即如果你是这样
Thread t1 = new Thread(runnable);
t1.start();
它必须把它放在堆上。
【讨论】:
在 Java 中没有办法在栈上分配对象。
堆栈只能保存引用和原语,并且只能保存局部变量。
请注意,启动一个线程将为该线程创建一个新堆栈。
【讨论】:
Thread 对象及其字段是在堆上分配的。与新线程关联的堆栈内存由 JVM/OS 分配,但它不是在堆上。它被分配在不同的内存部分中。