JVM中的内存分配

时间:2012-03-04 11:13:04

标签: java memory-management

我正在考虑Java中的内存分配,即其中 存储内存位置方法,字段和对象。

假设我有2个班级

import java.util.*;
class ABC
{
int field;
List<Integer>l;
}   
class XYZ 
{
int x,y,z;
static int p;
void fun(ABC a){
    a.field = 10;
    a.l = new ArrayList<Integer>(10);
    a.l.add(10);
}
}   
public class Simulator{
public static void main(String[] arg){
    XYZ tmp_1 = new XYZ();
    ABC tmp_2 = new ABC();
    tmp_1.fun(tmp_2);
    System.out.println(tmp_2.l);
}

}

现在将为每个数据成员分配内存,分配函数和对象?

我的想法是对象,数据成员将存储在堆中,但我不确定函数及其数据成员?

3 个答案:

答案 0 :(得分:4)

是的,所有对象都在堆上分配。即:使用new创建的所有内容都将放在堆上。因此,这些对象的所有字段也都在堆上。

我想你是指函数中的局部变量和参数。它们被放置在堆栈上(对于函数的每次调用)。但请注意,当函数变量/参数是引用类型时,它们指向的实际对象在堆上,但变量/参数本身将在堆栈上(类似于C / C ++中的指针)。另一方面,基本类型的函数变量/参数(如intdouble等)将完全在堆栈上。与主题略有相关但又相关的是boxing的概念。

函数本身是静态代码,存储在所有可执行代码所在的内存的特殊部分中。请注意,类的所有实例共享相同的功能(即,即使这些函数是实例函数),也不会使用新创建的对象创建“新函数”。因此,当您在对象上调用实例函数时,会向该函数传递一个特殊的this引用(它是函数的隐式参数)。这就是函数知道它应该在哪些对象上运行的方式。

答案 1 :(得分:1)

以下是您存储或提及的不同内容的细分:

  • 局部变量和方法/构造函数参数可以包含原始值或对象或数组的引用。 (它们不能包含对象或数组本身。)本地和参数存储在激活帧中(使用JLS术语),这些帧存储在线程的堆栈中。线程堆栈是典型JVM中的非堆内存。

  • 对象和数组在堆内存中表示。

  • 实例字段(包含基元或参考值)存储在对象中,因此存储在堆中。

  • 数组元素(基本值或引用值)和数组的长度存储在数组中,因此存储在堆中。

  • 静态字段存储在称为静态帧的特殊帧中。这些帧存储在堆中。

  • Java方法的代码(字节代码和本机代码形式)通常由存储在堆中的代码块表示。


请注意,上述内容基于典型 JVM中发生的情况。事实上,Java语言规范并没有要求将事物存储在堆栈或堆中。堆栈内存和堆内存这两个术语根本不会出现在JLS中,可以想象可以使用其他内存组织方案。

此外,“堆”过度简化,因为HotSpot JVM / GC通常将堆分成具有不同特征的区域。例如,堆的“permgen”区域(分配静态帧和代码块)只是很少收集垃圾。

答案 2 :(得分:0)

补充以前的答案:

  1. 函数存储在特殊区域中,但对它们的引用存储在对象中(对于非静态函数)。
  2. 对静态函数的引用存储在另一个区域(您可以认为它们存储在静态字段旁边)(静态内存区域)。
  3. 所有对象都存储在堆(对象池)中,但它们的引用位置各不相同,局部变量位于堆栈中,非静态字段存储在对象本身中,因此它们也存储在堆中。 / LI>
  4. 静态引用放在内存的另一个特殊部分中(尽管如果它们是对象的引用,它们指向堆)。