class,object,reference变量在哪里存储在java中。在堆或堆栈?堆或堆栈在哪里?

时间:2012-11-29 11:11:45

标签: java

我理解方法的变量存储在堆栈中,类变量存储在堆中。那么我们创建的类,对象在哪里存储在java

8 个答案:

答案 0 :(得分:55)

JVM中的运行时数据区域可以划分如下,

  1. 方法区域:已编译类文件的存储区域。 (每个JVM实例一个)

  2. 堆:对象的存储区域。 (每个JVM实例一个)

  3. Java堆栈:本地变量的存储区域,中间操作的结果。 (每个线程一个)

  4. PC寄存器:如果下一条指令是本机方法,则存储下一条要执行的指令的地址,然后pc寄存器中的值将是未定义的。 (每个线程一个)

  5. 本机方法堆栈:帮助执行本机方法(用Java以外的语言编写的方法)。 (每个线程一个)

答案 1 :(得分:23)

以下是您需要考虑的关于java中内存分配的要点。

注意:对象和对象引用是不同的东西。

1)java中有 new 关键字经常用于创建新对象。但新功能是为您正在创建的类的对象分配内存并返回引用。

这意味着每当您将对象创建为静态或本地对象时,它都会存储在 HEAP 中。

2)所有类变量原语或对象引用(它只是指向存储对象的位置的指针,即堆)也存储在堆中。

3)由类加载器加载的类静态变量静态对象引用存储在堆中的一个特殊位置,即永久生成。< / p>

4)本地原始变量本地对象引用方法参数存储在Stack中。

5)本地函数(方法)存储在堆栈中,但静态函数(方法)存放在永久存储中。

6)所有与类相关的信息,如类的名称,与类关联的Object数组,JVM使用的内部对象(如java / lang / Object)和优化信息都会进入永久代际区。

7)要了解堆栈,堆,数据,您应该阅读有关操作系统中的进程和进程控制块的信息。

答案 2 :(得分:12)

Java中的所有对象都存储在堆上。保存对它们的引用的“变量”可以在堆栈上,也可以包含在其他对象中(然后它们不是真正的变量,而是字段),这也将它们放在堆上。

定义类的Class对象也是堆对象。它们包含构成类的字节码(从类文件加载),以及从中计算的元数据。

答案 3 :(得分:7)

内存的堆栈部分包含方法,局部变量和引用变量。

堆部分包含对象(也可能包含引用变量)。

在短暂的谷歌之后,我找到了一个描述它的链接,是 youtube video 链接。 ^ _ ^

http://www.youtube.com/watch?v=VQ4eZw6eVtQ

答案 4 :(得分:2)

局部变量(方法变量)+方法存在于堆栈中。虽然对象及其实例变量存在于堆上。

现在,Reference变量可以是局部变量(如果在方法内创建)或实例变量(如果在类内创建,但在外部方法中)。因此引用变量可以是堆栈或堆栈中的任何位置。

答案 5 :(得分:2)

根据JVM规范,

类和它自己的常量池,即静态变量存储在方法区中。 这里的类只包含一堆字段,方法和常量,这些方法以指令的形式存储在方法区中,可以通过地址识别。

对象只是一个将在堆区域中创建的填充类模板,但对象引用是在堆栈中创建的。

public class Sample{
int field;
static int constant;
public void test(){
int localVariable=10;
Sample samp=new Sample();
  }
}

在这个例子中, sample.class将转到Method Area,这意味着&#39; field&#39;,&#39; constant&#39;和方法&#39;测试&#39;在方法区域中分配。

执行开始时 新Sample()创建的对象将转到但是&#39; samp&#39;只是一个对象引用,它进入堆栈并保存

中存在的对象的地址

有关详细信息,请查看此链接, JVM Specification

答案 6 :(得分:1)

这个概念很简单:

  1. 实例变量(原始变量,包装类,引用,对象(非静态))-堆
  2. 局部变量,参考-堆栈
  3. 其他数据对象,例如:类元数据,JVM代码,静态变量,静态对象引用,静态函数等,以前曾经存在于Permgen Space(直到Java 7)中,现在已移至JAVA 8中的Metaspace。

PS:元空间是本机内存的一部分,因此现在无需担心OOM:Pergem Exeption。

有关更多详细信息:https://siddharthnawani.blogspot.com/

答案 7 :(得分:0)

在Java中,变量可以保存对象引用(s中的String s="OOO"保存对象"OOO"的引用)或i中的原始值(int i=10 {1}}拥有10)。这些变量可以在堆或堆栈上,具体取决于它们是否为本地变量以及您正在使用的JVM的哪种风格。

在Java虚拟机8规范文档(https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html)中,与此相关的内存组织如下。

  1. 每个Java线程都有自己的JVM堆栈。

      

    它包含局部变量和部分结果,并参与其中   方法调用和返回。

    堆栈中也可能存在对象引用。的的 规范不区分原始变量 和参考变量,只要它是本地。使用此堆栈 称为帧的数据单位。但是,

      

    因为Java虚拟机堆栈永远不会被直接操作   除了推送和弹出帧之外,帧可能是堆分配的。

    因此,它取决于框架所在的JVM规范(如OpenJDK或Oracle)的实现。

  2. 每个JVM实例都有一个堆。堆是

      

    ...所有类实例和内存的运行时数据区   数组已分配。

    保存对象数据的实际内存驻留在堆上。该 堆在所有JVM的线程之间共享。这还包括对象 引用,它们是对象的一部分,即实例变量。

    例如,请参加以下课程。

    class Moo{ private String string= "hello"; } class Spoo{ private Moo instanceReferenceVariable = new Moo(); public void poo(){ int localPrimitiveVariable=12; Set<String> localReferenceVariable = new HashSet<String>(); } }

    这里变量引用的对象instanceReferenceVariable
    将在堆上,因此该对象的所有实例变量,如 string,也将在堆上。变量localPrimitiveVariablelocalReferenceVariable将在堆栈中。

  3. 方法区域:方法区域是堆的受限制部分

      

    ...存储每类结构,例如运行时常量池,   字段和方法数据,以及方法和构造函数的代码,   包括类和实例中使用的特殊方法   初始化和接口初始化。

  4. 运行时常量池:这是方法区域的一部分。

  5. 希望这能澄清事情。