这个问题特别针对java语言。我知道为所有静态代码留出了静态内存。

我的问题是这个静态内存是如何填充的?静态对象是在导入时还是在第一次引用时放入静态内存?此外,相同的垃圾收集规则是否适用于静态对象,因为它们适用于所有其他对象?


public class Example{
    public static SomeObject someO = new SomeObject();
}
/********************************/
// Is the static object put into static memory at this point?
import somepackage.Example;

public class MainApp{
    public static void main( Sting args[] ){
// Or is the static object put into memory at first reference?
       Example.someO.someMethod();
// Do the same garbage collection rules apply to a 
//     static object as they do all others?
       Example.someO = null;
       System.gc();
    }
}
有帮助吗?

解决方案

导入与编译代码中的任何指令都不相关。它们只在编译时建立别名。

有一些反射方法允许加载类但尚未初始化,但在大多数情况下,您可以假设每当引用类时,它都已初始化。

执行静态成员初始值设定项和静态块,就好像它们都是源代码顺序中的一个静态初始化程序块一样。

在卸载类之前,强烈引用通过静态成员变量引用的对象。普通的 ClassLoader 从不卸载类,但应用程序服务器使用的类在正确的条件下执行。然而,这是一个棘手的领域,并且是许多难以诊断的内存泄漏的来源,而另一个原因是不使用全局变量。


作为(切向)奖金,这是一个需要考虑的棘手问题:

public class Foo {
  private static Foo instance = new Foo();
  private static final int DELTA = 6;
  private static int BASE = 7;
  private int x;
  private Foo() {
    x = BASE + DELTA;
  }
  public static void main(String... argv) {
    System.out.println(Foo.instance.x);
  }
}

此代码会打印什么?尝试一下,你会看到它打印“6”。这里有一些工作,一个是静态初始化的顺序。执行代码就好像它是这样写的:

public class Foo {
  private static Foo instance;
  private static final int DELTA = 6;
  private static int BASE;
  static {
    instance = null;
    BASE = 0;
    instance = new Foo(); /* BASE is 0 when instance.x is computed. */
    BASE = 7;
  }
  private int x;
  private Foo() {
    x = BASE + 6; /* "6" is inlined, because it's a constant. */
  }
}

其他提示

通常没有“静态”的东西。记忆。大多数vm都有堆的永久生成(其中类被加载),这通常不是垃圾回收。

静态对象的分配方式与任何其他对象一样。但是,如果它们存活很长时间,它们将在垃圾收集器中的不同代之间移动。但它们不会最终进入permgenspace。

如果您的类永久保留此对象,则仅在vm退出时才会释放。

只要在代码中引用了类,就会初始化此静态变量 some0 。在您的示例中,这将在main方法的第一行执行。

您可以通过创建静态初始化程序块来验证这一点。在此初始化程序块中放置一个断点,您将看到它何时被调用。或者更简单......在SomeObject的构造函数中放置一个断点。

静态变量的初始化在 2.11静态初始化器。规范没有定义垃圾收集的实现,但是我想静态对象的垃圾收集规则会因你的VM而异。

应该注意,只有指针(或任何其他原始类型)存储在 PermGenSpace (这是存储静态内容的区域的正确名称)。

因此指针引用的Object与任何其他对象一样位于普通堆中。

如果更改静态字段以引用其他对象,则静态字段指向的原始对象与其他任何对象一样符合GC的条件。

如果类本身被卸载并且从堆中剪切整个对象图,它也可以是自由的(即使不是空的)。当然,当一个类可以被卸载时,对于许多其他问题来说是一个很好的主题......:)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top