静态方法(实际上所有方法)以及静态变量都存储在堆的部分中,因为它们是反射数据的一部分(类相关数据,而不是实例相关数据)。从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 的变化, 所以我想以上对于那个版本仍然是正确的,但我不确定这里。