运行时与java中的编译时内存分配

时间:2012-09-05 16:00:10

标签: java allocation

我很困惑java中的内存分配是在运行时还是编译时发生。

例如:

class Test{
  int a;
  public Test(){
    a=10;
  }
};

// somewhere else
Test t = new Test();

在运行时或编译时分配a吗?如果在编译时,如何在直接获取编译的.class文件的VM上运行java?

此外:

  • a何时分配了值10

  • 它如何用于引用变量t

感谢。

4 个答案:

答案 0 :(得分:6)

编译时不会发生内存分配。仅在加载和运行时。

编译时会生成.class文件。

请记住,您需要有一个主类来运行该程序。使用带有classpath到.class文件的Java运行程序时,会出现诸如loading& amp;链接等,

类加载器将文件加载到permgen。

当调用main方法时,将创建堆栈并将局部变量放在那里

当运行时遇到 new 时,它会在堆上创建对象并在那里分配所需的内存,就像测试所需的内存一样。

答案 1 :(得分:3)

本地变量和方法参数(如基元或引用)在编译时在名义上在堆栈上分配一个位置。

在运行时,无法保证能够反映它在内存中的布局方式。

堆上对象的分配仅在运行时发生。

  

如何在VM上运行直接获取编译.class文件。

只有VM知道如何编译代码,因此无法在编译时进行内存分配。

  

何时是指定值10

在分配发生的行。鉴于它没有被使用,JIT可以丢弃它,因此根本不会发生。

  

同样的问题代表参考变量t。

t分配在构造对象后=所在的位置。

答案 2 :(得分:1)

嗯,这个有点麻烦,我不确定你是否会从整个帖子中得到你想要的确切答案,因为真的,你是什么'再问,是编译器内部的主要话语,大多数人都不在乎。

在大多数情况下,Java编译器使用自动内存管理,因此编译器确定它将做什么或不做什么,这可以在不同版本之间进行更改。

但在我开始解释之前,我想澄清我的注释:

  1. 当引用不是a的Java对象时,我将使用[Object] 原始。
  2. 当引用内存中具有值和标识符的位置时,我将使用[object]。
  3. 我将使用[primitive]来引用由Java中的一个基本类型组成的[object](int,double,float, 等等,不包括字符串)
  4. String是java中的一个特例,虽然它是一个对象,但它的处理方式可能与其他对象不同。

    [object]有一个特殊属性。它具有值和标识符,以及将标识符解析为值并在何时发生的过程取决于绑定的类型。

    存在静态绑定,其中绑定可以在编译时解析,并且其值或方法在编译时是已知的。这也被称为"早期"捆绑。例如。

    int a = 0; // AND //一个直接的函数调用,比如print();

    还有动态绑定,其中标识符与值或子程序之间的绑定在程序运行之前不会发生。这也被称为"晚期"捆绑。例如。

    public void foo(java.util.List list){     list.add("杆&#34); }

    这也是一种混合类型的绑定,但我不打算谈论这个,因为我还没有发现Java拥有它。

    现在,绑定也与范围界定密切相关,这是一个变量"生活"在一定范围内。这是一个我真正不想进入的话语主题(范围有点像熊)并且使这篇文章成为小说而不是中篇小说。

    Java中的内存分配方式取决于以下几点:

    1. 如果在编译时已知对[Object],[object]或[primitive]的引用,并且可能发生静态绑定,则编译器可能会为这些对象分配内存(注意我在编译时没有使用括号)。

    2. 如果在编译时无法识别对[Object],[object]或[primitive]的引用,并且必须使用动态绑定,则编译器可能会在运行时为这些对象分配内存。

    3. Java处理在运行时分配的对象的方式区分取决于使用哪种类型的绑定。

      1. 静态绑定
        • 作为一种[Object]的对象将在编译时将它们的引用放在堆栈上,但它们的内存在运行时分配在堆上。 (懒)。
        • 作为一种[primitive]的对象将在运行时绑定并分配。
        • 字符串是一种特殊情况,但通常像[Object]
        • 一样处理
      2. 后期绑定
        • 在运行时完成堆栈和堆上的分配。
      3. 总之,不要担心。这样做会让你头疼。

        如果我对此有任何不妥之处,请有人告诉我。我有点生疏了。

答案 3 :(得分:1)

在java中,除非创建在运行时创建的对象,否则不会加载类,因此任何成员变量(如“a”)都会在加载类时获得空间,对于对象,它将在运行时分配空间。