【发布时间】:2011-01-09 16:13:07
【问题描述】:
如果我们将对象存储在对象的静态字段中,JVM 是如何为它分配内存的?它是否存在于“隐式”(不确定我是否使用正确的词)类对象中?静态字段与对象字段有何不同?
【问题讨论】:
-
静态字段在第一次调用封闭类型时被初始化,并且可以从该类型的任何实例访问它们。
-
请记住,静态字段引用的对象只是普通对象,因此任何特定实现如何处理静态字段并不重要。
如果我们将对象存储在对象的静态字段中,JVM 是如何为它分配内存的?它是否存在于“隐式”(不确定我是否使用正确的词)类对象中?静态字段与对象字段有何不同?
【问题讨论】:
静态字段是类变量,在该类的所有实例之间共享。实例变量(或我认为您所指的对象字段)属于类的各个实例并且不共享。
至于它们在内存中的存储位置将取决于 JVM 的实现,并且没有理由要求两个不同的 JVM 按规范将它们存储在同一个位置(至少据我所知) - 应在此处插入适当的规格表链接)。
【讨论】:
正如尼克的回答所说,语言规范没有规定特定的“物理”位置,但就您可以推理的逻辑思维模型而言,它可能有助于您将静态字段视为附加到这些字段所属的类的类对象 (Foo.class)。
顺便说一句,类对象在处理静态实体时以其他方式使用(由语言规范规定):例如,当调用synchronized 静态方法时,锁定在该方法所属的类的类对象上。
【讨论】:
synchronized 的静态方法,它会锁定类对象,因为静态方法没有this 引用。 (非静态 synchronized 方法在调用时锁定 this,而不是类对象。)
正如 NickLarsen 所说,我认为没有任何 JVM 规范如何准确存储静态字段。编译定义的常量(静态最终)将很可能在编译期间替换表达式。对于可变静态字段,只有两个选项:堆或(如果存在)JVM 的数据段。
【讨论】:
静态字段是类的一部分;据说,当类被卸载时,它们会消失。将它们想象成接近类的Class 实例是有道理的。 Java 应用程序无法获取有关内存布局的详细信息;作为推论,JVM 规范对这个主题没有任何具体要求。甚至在类卸载时字段的“消失”也无法直接观察到,只能通过 GC 操作,假设放置良好的 finalize() 方法。
【讨论】:
静态字段存储在 Class 对象中,该对象保存在 PemGen 空间中。这是堆内存的一部分。
【讨论】: