Java 中静态方法和静态变量存储在哪里?

2022-08-31 08:03:07

例如:

class A {
    static int i=0;
    static int j;

   static void method() {
       // static k=0; can't use static for local variables only final is permitted
       // static int L;
    }
}

这些变量将存储在 Java、堆或堆栈内存中的什么位置?它们是如何存储的?


答案 1

静态方法(实际上所有方法)以及静态变量都存储在堆的部分中,因为它们是反射数据的一部分(类相关数据,而不是实例相关数据)。从Java 8开始,PermGen已被MetaSpace取代,根据JEP 122,它只保存元数据,而静态字段存储在堆中。PermGen

请注意,这主要适用于Oracle的Hotspot JVM以及基于它的其他JVM。然而,并不是每个JVM都有PermGen或Metaspace,比如Eclipse OpenJ9

澄清的更新

请注意,只有变量及其技术值(基元或引用)存储在 PermGen 空间中。

如果静态变量是对对象的引用,则该对象本身存储在堆的正常部分(年轻/老一代或幸存者空间)中。这些对象(除非它们是内部对象,如类等)存储在PermGen空间中。

例:

static int i = 1; //the value 1 is stored in the PermGen section
static Object o = new SomeObject(); //the reference(pointer/memory address) is stored in the PermGen section, the object itself is not.

关于垃圾回收的一句话:

不要依赖,因为它不能保证运行。完全由 JVM 决定何时运行垃圾回收器以及收集什么,即使某个对象符合垃圾回收的条件。finalize()

当然,您可以将静态变量设置为 null,从而删除对堆上对象的引用,但这并不意味着垃圾回收器收集它(即使没有更多的引用)。

此外,它只运行一次,因此必须确保它不会引发异常或以其他方式阻止收集对象。如果通过某些异常停止了终结,则不会再次在同一对象上调用。finalize()finalize()

最后要注意的是:如何存储代码,运行时数据等取决于所使用的JVM,即HotSpot可能与JRockit不同,这甚至可能在同一JVM的版本之间有所不同。以上是基于 Java 5 和 6 的 HotSpot(基本相同),因为在回答时,我会说大多数人都使用了这些 JVM。由于 Java 8 内存模型的重大变化,上面的语句可能不适用于 Java 8 HotSpot - 而且我没有检查 Java 7 HotSpot 的变化, 所以我想以上对于那个版本仍然是正确的,但我不确定这里。


答案 2

在 Java 8 之前:

静态变量存储在permgen空间(也称为方法区域)中。

PermGen Space也被称为Method Area。

PermGen Space曾经存储3件东西

  1. 类级数据(元数据)
  2. 实习字符串
  3. 静态变量

从 Java 8 开始

静态变量存储在堆本身中。从Java 8开始,PermGen Space被删除,并引入了名为MetaSpace的新空间,这与之前的Permgen Space不再是Heap的一部分。Meta-Space 存在于本机内存(操作系统提供给特定应用程序的内存供其自己使用)上,现在它只存储类元数据。

暂存字符串和静态变量将移动到堆本身中。

有关官方信息,请参阅:JEP 122:删除永久的Gen空间


推荐