论坛首页 Java企业应用论坛

java 类的生命周期

浏览 19339 次
精华帖 (1) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-04  
OO

好长的一段时间,对于类的生命周期十分模糊,现在经过一段时间的学习,对于类的生命周期的理解已经变得清晰,类的生命周期如下所示:

 

    类的装载就是通过类加载器把.class二进制文件转入jvm的方法区,并在堆区创建描述该类的java.lang.Class对象,用来封装数据。如果要获取这个Class对象可以通过实例的getClass()或者直接通过的类的静态方法.class。JVM规范允许预先加载,在预料到某个类要使用的时候就加载这个类,如果这个类不存在,也不会马上抛出异常,只有在程序主动使用这个类的时候才会抛出异常,如果这个类一直没有使用,那么就永远不会抛出异常。

 

    对于验证是验证加载的二进制文件是否符合规范,如有没有继承final类等。

    准备就是为静态成员分配内存空间,并设置默认值,byte short long flloat 都是0,对象类型为null,boolean类型为false.

    解析就是对于编译型常量使用直接的内存地址代替变量,如final static int a = 10;但是对于在编译的时候不能得到具体值得变量不做变换,如final static int a = Math.random()。在完成上述工作后,就是对于静态变量的初始化。

   对于静态变量的初始化时在主动使用的时候才会初始化他们。以下6种情况是主动使用

   创建类的实例,途经包括:使用new 创建对象实例,clone等

   使用反射方法

   使用静态方法

   使用类或者接口的静态变量,给静态变量赋值

   创建子类

   把类声明为启动类,如: java Test01

   这时候会初始化类的静态变量,执行静态代码块

   我想主要说一下类的卸载:只有没有任何引用指向Class对象的时候,这时候才会卸载类,结束类的生命周期。在JVM中有三类加载器 根加载器,扩展加载器,系统加载器,JVM始终保持这几类加载器的引用,加载器会把其加载的类放在一个集合中,这样就保留着对于Class对象的引用(不可以操作JVM的加载器),所以由JVM的加载器加载的类是不会卸载的,如果要验证一个类是否可以卸载,可以自己创建一个类加载器(继承ClassLoader) Loader,加在一个类Test,然后让loader的实例赋值为null,loader加载的Class对象也赋值为null;再次创建Loader的实例,并加载Test,这时候可以打印这两个Test的Class对象的哈希值(是不一样的),如一下代码(加载器MyclassLoader.java不给出了):

java 代码
  1. public class MainTest01    
  2. {   
  3.   
  4.     public static void main(String[] args)    
  5.     {   
  6.         MyClassLoader loader = new MyClassLoader();    
  7.         Class clazz = loader.findClass("Test");   
  8.         System.out.println(clazz.hashCode());   
  9.         loader = null;   
  10.         clazz = null;   
  11.         loader = new MyClassLoader();   
  12.         clazz =loader.findClass("Test");   
  13.         System.out.println(clazz.hashCode());   
  14.     }   
  15.   
  16. }   

   如果注释掉第9句,那么会抛出类重复加载异常。

   发表时间:2007-05-08  
引用
我想主要说一下类的卸载:只有没有任何引用指向Class对象的时候,这时候才会卸载类,结束类的生命周期。

长知识了
0 请登录后投票
   发表时间:2007-05-08  
xly_971223 写道
引用
我想主要说一下类的卸载:只有没有任何引用指向Class对象的时候,这时候才会卸载类,结束类的生命周期。

长知识了

我记得是如果一个类对象没有被引用的话,会被垃圾收集器回收,如果被集合类引用的话,只将集合类设置为空的话,并不能被回收。
0 请登录后投票
   发表时间:2007-05-09  
rainlife 写道
xly_971223 写道
引用
我想主要说一下类的卸载:只有没有任何引用指向Class对象的时候,这时候才会卸载类,结束类的生命周期。

长知识了

我记得是如果一个类对象没有被引用的话,会被垃圾收集器回收,如果被集合类引用的话,只将集合类设置为空的话,并不能被回收。


他说的是类的卸载,不是对象实例的释放。
0 请登录后投票
   发表时间:2007-05-09  
想知道findclass是怎么实现的,从中没有看出 类是怎么卸载的,Class对象每次生成 hashcode都会不同吧,在例子中不同就能说明是重新加载的么?
0 请登录后投票
   发表时间:2007-05-09  
我只是想示意一下,我并没有写一个MyClassLoader类,但是对于描述类数据结构的java.lang.Class对象来讲,一个类肯定只有一个。
hashtable是用散列的方式来存储对象,散列算法采用的基数就是hashcode,也就是说根据某个对象的hashcode和某种算法从而找到table中的某个位置,取到这个位置存储的对象。在java中hashcode默认使用对象的内存地址的。
对于“Class对象每次生成 hashcode都会不同吧,在例子中不同就能说明是重新加载的么?”----对于描述类的Class对象与类紧密相关,如果不断改变的话,那么对于类实例getClass()所获取的引用就要不断改变了
可以试一下:使用Class.forName()获取一个类的Class对象,多次获取每一次得到的hashcode必然一样

非常喜欢这样开放的环境,大家讨论一下,都会受益!
非常感谢各位的留言,希望我们一起进步!
  
0 请登录后投票
   发表时间:2007-05-10  
Godlikeme 写道
想知道findclass是怎么实现的,从中没有看出 类是怎么卸载的,Class对象每次生成 hashcode都会不同吧,在例子中不同就能说明是重新加载的么?

hashcode不同说明这个class实例重新加载了一次(跟前一个class实例不同)
如下:
A.class已经被加载hashcode为1 如果A.class不卸载 再次加载肯定失败 jvm不允许重复加载
除非A.class已经卸载 所以再次加载后产生一个新的A.class实例,其hashcode为2(当然还有可能为1)
两次的hashcode不同基本可以确定A.class被重新加载
0 请登录后投票
   发表时间:2007-05-10  
在同一个classLoader里面是class实例只有一个,可在上面的例子中是使用了两个classLoader,
还有例子中用的是classloader.findclass,和class.forname明显不是一回事。
如果我没有记错,同一个版本的class可以在不同的classLoader中加载,是不同实例,当然hashcode不同。
所以,请继续回答我前一个问题。
0 请登录后投票
   发表时间:2007-06-07  
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()
0 请登录后投票
   发表时间:2007-06-07  
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

调用system.gc()也不会马上进行垃圾回收的吧。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics