关于class的GC问题

源文见:http://www.iteye.com/problems/8266

 

首先要区分清code和data。以后JVM很可能会有新的机制来允许方法(code)被GC,例如说通过新的AnonymousLoader、MethodHandle等机制。但就现在的JVM来说,code一旦被ClassLoader给load进来之后就放在PermGen heap上,基本上直到程序终止前都不会被GC了。据说Java 6 Update 4还是多少开始有个新的启动参数,-XX:+ExplicitGCInvokesConcurrentAndUnloadsClasses,不过没仔细看不知道到底能达到怎样的效果。 

Java中的code是以类为单位保存在class文件里的。Class文件里含有类的名称、继承关系、常量池,以及各个静态/成员方法的字节码。JVM在加载程序的时候也是以类为单位来加载的,code会被加载到称为"Permanent Generation"(PermGen)的堆上。 

类的静态变量是在其被加载时先分配空间(可以认为也是在PermGen里),然后初始化。其生命周期与类的code的生命周期一样长。 
成员变量则是在new新的实例时分配空间,并由默认初始化器和构造器等初始化。其生命周期与实例的周期相关。注意这里说的生命周期是单纯指primitive type或者reference自身,而不包括reference指向的对象。举例来说,假如一个实例a的成员x被赋为null了,那么这个null值仍然要保存在a里,在32位系统上这就意味着至少占用了4个字节。 

方法中的局部变量概念上说是在栈上分配空间的,其生命周期与方法调用的周期一样,也就是说方法调用过后空间就会被回收。注意这里指的同样是primitive type或者reference自身,而不包括reference所指向的对象。再举个例子的话,假如在方法里有这么一句:

Java代码:
  1. String s = new String("abc");  

则"abc"是在常量池里分配空间的,s现在所指向的刚new出来的对象(作为一个实例)是在第0代堆里分配空间,而s(作为一个引用)自身概念上是在栈上分配空间的。方法结束时,s自身的空间会被回收,但s所指向的对象是否被回收取决于是否还存在指向它的活引用。 

之所以说是“概念上在栈上分配空间”是因为JVM有可能会将局部变量优化为直接分配在寄存器上,不过这是实现细节,对上层的程序员并没有可见的影响。 

基本上就是这样吧……

你可能感兴趣的:(jvm)