这个问题特别针对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(); } }
erickson.. 34
导入与编译代码中的任何指令都不相关.它们仅在编译时建立别名.
有一些反射方法允许加载类但尚未初始化,但在大多数情况下,您可以假设每当引用类时,它都已初始化.
执行静态成员初始值设定项和静态块,就好像它们都是源代码顺序中的一个静态初始化程序块一样.
在卸载类之前,强引用通过静态成员变量引用的对象.正常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. */ } }
krosenvold.. 5
通常没有"静态"记忆这样的东西.大多数vm都有堆的永久生成(其中类被加载),这通常不是垃圾回收.
静态对象的分配方式与任何其他对象一样.但是,如果它们存活很长时间,它们将在垃圾收集器中的不同代之间移动.但它们不会最终进入permgenspace.
如果您的类永久保留此对象,则只有在vm退出时才会释放它.
导入与编译代码中的任何指令都不相关.它们仅在编译时建立别名.
有一些反射方法允许加载类但尚未初始化,但在大多数情况下,您可以假设每当引用类时,它都已初始化.
执行静态成员初始值设定项和静态块,就好像它们都是源代码顺序中的一个静态初始化程序块一样.
在卸载类之前,强引用通过静态成员变量引用的对象.正常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退出时才会释放它.