是否可以将对象存储在堆栈上而不是 Java 中的堆上?

2022-09-04 20:53:28

是否可以将对象存储在堆栈而不是堆上?

我最近浏览了这个博客 http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/

是否可以将对象存储在堆栈而不是堆上?

是的,对象可以存储在堆栈上。如果在函数内创建一个对象而不使用“new”运算符,那么这将创建对象并将其存储在堆栈上,而不是堆上。假设我们有一个名为 Member 的C++类,我们要为其创建一个对象。我们还有一个名为 somefunction( ) 的函数。代码如下所示:

他们建议对象可以存储在堆中。这令人困惑。

我以为,

  1. Java 中的所有对象都存储在堆上。
    它是否由
    a.
    b 创建。使用
    c.使用
    d.使用方法
    e. 使用对象反序列化。new KeywordClass.forName().clone().newInstance()

  2. 方法,线程和变量在堆栈中。

  3. 类变量(静态变量)存储为与该类关联的 Class 对象的一部分。这个类对象只能由 JVM 创建,并存储在永久生成中。

如果我错了,请纠正我。

现在我怀疑对象是否可以以任何形式驻留在或存储在堆栈中。

谢谢。


答案 1

所有类实例都存储在堆中。

以下是一些可靠的来源:
来自JVM spec:
https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf

2.5.3 堆

Java 虚拟机有一个在所有 Java 虚拟机线程之间共享的堆。堆是运行时数据区域,从中为所有类实例和数组分配内存。

来自 Java 语言规范:
https://docs.oracle.com/javase/specs/jls/se8/jls8.pdf

17.4.1 线程之间可以共享的共享变量

内存称为共享内存或堆内存。所有实例字段、静态字段和数组元素都存储在堆内存中。


答案 2

您的观点 (1):所有对象都在堆上分配。

这几乎是真的。对象始终在堆上分配。但是,如果对象的转义分析允许,则可以在堆栈上分配对象(它仅对调用方法可见,并且不会在堆栈外部转义),如 IBM 网站上的本文所述。

但是,请注意,Oracle 特别指出,由于本技术说明中的转义分析,它不会将堆分配替换为堆栈分配。

所以,是的,对象总是在(Oracle)Java的堆上。


你的观点(2):方法,线程和变量都在堆栈上。

否,方法和线程不在堆栈上。局部变量和参数放置在堆栈上。在每个方法调用时,都会准备一个堆栈帧,并为参数、返回值和局部变量在其中分配空间。

方法本身是类的一部分。线程对象的分配与任何其他对象一样,但线程本身不是数据,也不是分配的,而是为它们分配的堆栈。


你的观点(3):静态变量在PermGen上分配。

在Java 8之前,这些信息都是正确的。根据JEP 122,它们现在被分配在堆上,因为PermGen已被消除。

请注意,JVM 的不同实现之间的实现细节是不同的。其他JVM甚至在Java 8之前就已经摆脱了PermGen。


推荐