一个对象可以存储在堆栈而不是Java中的堆中吗?

时间:2015-09-10 11:16:11

标签: java

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

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

  

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

     

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

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

我想到了,

  1. Java中的所有对象都存储在堆中 是否由
    创建 一个。 new Keyword
    湾使用Class.forName().
    C。使用clone().
    d。使用newInstance()方法
    即使用对象反序列化。

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

  3. 类变量(静态变量)存储为与该类关联的Class对象的一部分。此Class对象只能由JVM创建,并存储在永久生成中。
  4. 如果我错了,请纠正我。

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

    谢谢。

3 个答案:

答案 0 :(得分:5)

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

以下是一些可靠的消息来源:
来自JVM规范:
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共享变量

  可以在线程之间共享的内存称为共享内存或   堆内存。所有实例字段,静态字段和数组元素   存储在堆内存中。

答案 1 :(得分:3)

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

这是非常正确的。对象始终在堆上分配。但是,如果对象可以在其堆栈上进行转义分析(它只对调用方法可见,并且不会在其外部转义),则可以在堆栈上分配 ,如{{3}中所述。在IBM网站上。

但请注意,Oracle明确表示,由于this article中的转义分析,它确实 用堆栈分配替换堆分配。

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

您的观点(2):方法,线程和变量在堆栈中。

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

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

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

这个信息在Java 8之前是正确的。根据this technical note,它们现在被分配在堆上,因为PermGen已被淘汰。

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

答案 2 :(得分:2)

必须在堆中分配所有Java对象:

JVMS 8 2.5.3

  

[...]堆是运行时数据区,所有类的内存   实例和数组已分配

但是,由于escape analysis,某些对象可能会优化为基本类型并存储在堆栈中。在这种情况下,他们从未真正成为对象,因此并没有真正违反规则。