`
pippo25
  • 浏览: 29503 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
最近访客 更多访客>>
社区版块
存档分类
最新评论

java 类的生命周期

阅读更多

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

 

    类的装载就是通过类加载器把.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句,那么会抛出类重复加载异常。

分享到:
评论
22 楼 ido158 2007-08-30  
javastudy 写道
jackhlp 写道
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

调用system.gc()也不会马上进行垃圾回收的吧。


调用system.gc()就是强制回收啊
,建议看看书


垃圾收集器系统有自己的一套方案来判断哪个内存块是应该被回收的,哪个是不符合要求暂不回收的。垃圾收集器在一个Java程序中的执行是自动的,不能强制执行,即使程序员能明确地判断出有一块内存已经无用了,是应该回收的,程序员也不能强制垃圾收集器回收该内存块。程序员唯一能做的就是通过调用System. gc 方法来"建议"执行垃圾收集器,但其是否可以执行,什么时候执行却都是不可知的。

还是建议你看看书吧!
21 楼 myyate 2007-07-31  
javastudy 写道
jackhlp 写道
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

调用system.gc()也不会马上进行垃圾回收的吧。


调用system.gc()就是强制回收啊
,建议看看书

我觉得看一下tjj就知道,即使调用system.gc()也不会马上进行垃圾回收的
20 楼 dennis_zane 2007-07-31  
hamburg 写道
jvm只要垃圾回收有很多种方式(具体不列出了),每一种方式都没有提出说必须系统面临崩溃的时候才被垃圾回收,只要该对象不再被任何引用,java虚拟机就会对她垃圾回收,你可以任意写一个类,在类中写这个finalize()在它中写上一些打印信息,然后你就知道他什么时候被回收了。到底是不是系统崩溃的时候被回收的。《java虚拟机原理》


这完全误导了吧,没有引用也不一定回收的,仅仅是可能被回收。虚拟机垃圾收集的触发是由虚拟机自行决定的,况且你也没有考虑到引用类。楼主所说的系统崩溃应该是用词错了。
19 楼 hamburg 2007-07-31  
jvm只要垃圾回收有很多种方式(具体不列出了),每一种方式都没有提出说必须系统面临崩溃的时候才被垃圾回收,只要该对象不再被任何引用,java虚拟机就会对她垃圾回收,你可以任意写一个类,在类中写这个finalize()在它中写上一些打印信息,然后你就知道他什么时候被回收了。到底是不是系统崩溃的时候被回收的。《java虚拟机原理》
18 楼 gfh21cn 2007-07-31  
java对象的生命周期是透明的,所以对于习惯C++的是有些不便
建议最好是能二者结合起来,支持手动释放,这样在管理大内存的时候更灵活,更快捷
17 楼 Garriot 2007-07-30  
关于这个类加载器的内存回收机制,《深入Java虚拟机》上有详细介绍。可以google一下。

我想问个问题是:按照Java的标准只有启动加载器加载的类是不可以回收的,自定义加载器加载的类是可以被回收的。那么我们都说PermGen Space out of memory 是由于sun JVM的一个bug导致的,那么这个bug是不是就是无法正常回收自定义加载器加载的那些类?
16 楼 galaxystar 2007-07-30  
能够引用到类的,一般就是静态内部方法,对吗?
所以,如果一个类有静态内部方法被引用着,那么这个类是不会被卸载的,对吗?
15 楼 Garriot 2007-07-30  
dennis_zane 写道
Garriot 写道
如果加载的元信息过多,这块空间一样会溢出,就是咱们平时见的PerGem Space out of memory.System.gc()应该是回收内存堆里的空间,不会来回收这里。关于PerGem Space的话题论坛里已经很多了,可以搜一下。


这块区域就是method area,方法区,所以sun的jdk调优要调整maxPermSize
而ibm的jdk没有独立的方法区,也是放在heap上


IBM的有没有我不是很清楚,但是我知道BEA的JRockit的是没有PermGen Space out of memory这个问题的,因为它里面根本就没有那块区域
14 楼 dennis_zane 2007-07-30  
Garriot 写道
如果加载的元信息过多,这块空间一样会溢出,就是咱们平时见的PerGem Space out of memory.System.gc()应该是回收内存堆里的空间,不会来回收这里。关于PerGem Space的话题论坛里已经很多了,可以搜一下。


这块区域就是method area,方法区,所以sun的jdk调优要调整maxPermSize
而ibm的jdk没有独立的方法区,也是放在heap上
13 楼 Garriot 2007-07-30  
hbcui1984 写道
javastudy 写道
jackhlp 写道
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

调用system.gc()也不会马上进行垃圾回收的吧。


调用system.gc()就是强制回收啊
,建议看看书


我也记得即使调用了System.gc(),也不一定立即进行垃圾回收阿

调用gc()只能告诉jvm说,我想现在运行垃圾回收,而jvm究竟什么时间进行,那是jvm自己的事,程序无权干涉。



关于这个问题我有两个个人观点:
第一,System.gc()是强制回收,但它并不是立即回收,它只是通知虚拟机你想进行一次强制内存回收,至于什么时候真正执行,这还得看虚拟机的策略。所以说它是强制的,但不是立即的。

第二,ClassLoader所加载的东西是类的元信息,这些信息应该是被保留在一块特殊的内存空间内的,System.gc()是影响不了这块空间的。如果加载的元信息过多,这块空间一样会溢出,就是咱们平时见的PermGen Space out of memory.System.gc()应该是回收内存堆里的空间,不会来回收这里。关于PermGen Space的话题论坛里已经很多了,可以搜一下。
12 楼 woodlin 2007-07-30  
gagagaa 类和对象的概念很重要嘛
11 楼 hbcui1984 2007-06-08  
javastudy 写道
jackhlp 写道
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

调用system.gc()也不会马上进行垃圾回收的吧。


调用system.gc()就是强制回收啊
,建议看看书


我也记得即使调用了System.gc(),也不一定立即进行垃圾回收阿

调用gc()只能告诉jvm说,我想现在运行垃圾回收,而jvm究竟什么时间进行,那是jvm自己的事,程序无权干涉。

10 楼 hbcui1984 2007-06-08  
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

系统资源不面临崩溃?是这样的吗?我记得好像是说垃圾回收是周期性进行的阿,用以释放无用对象所占用的内存。
9 楼 jackhlp 2007-06-07  
pippo25 写道
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()

调用system.gc()也不会马上进行垃圾回收的吧。
8 楼 pippo25 2007-06-07  
对是这样的,因为如果系统资源不面临崩溃,是不会触发垃圾回收的,除非是认为调用System.gc()
7 楼 Godlikeme 2007-05-10  
在同一个classLoader里面是class实例只有一个,可在上面的例子中是使用了两个classLoader,
还有例子中用的是classloader.findclass,和class.forname明显不是一回事。
如果我没有记错,同一个版本的class可以在不同的classLoader中加载,是不同实例,当然hashcode不同。
所以,请继续回答我前一个问题。
6 楼 xly_971223 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被重新加载
5 楼 pippo25 2007-05-09  
我只是想示意一下,我并没有写一个MyClassLoader类,但是对于描述类数据结构的java.lang.Class对象来讲,一个类肯定只有一个。
hashtable是用散列的方式来存储对象,散列算法采用的基数就是hashcode,也就是说根据某个对象的hashcode和某种算法从而找到table中的某个位置,取到这个位置存储的对象。在java中hashcode默认使用对象的内存地址的。
对于“Class对象每次生成 hashcode都会不同吧,在例子中不同就能说明是重新加载的么?”----对于描述类的Class对象与类紧密相关,如果不断改变的话,那么对于类实例getClass()所获取的引用就要不断改变了
可以试一下:使用Class.forName()获取一个类的Class对象,多次获取每一次得到的hashcode必然一样

非常喜欢这样开放的环境,大家讨论一下,都会受益!
非常感谢各位的留言,希望我们一起进步!
  
4 楼 Godlikeme 2007-05-09  
想知道findclass是怎么实现的,从中没有看出 类是怎么卸载的,Class对象每次生成 hashcode都会不同吧,在例子中不同就能说明是重新加载的么?
3 楼 weiqingfei 2007-05-09  
rainlife 写道
xly_971223 写道
引用
我想主要说一下类的卸载:只有没有任何引用指向Class对象的时候,这时候才会卸载类,结束类的生命周期。

长知识了

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


他说的是类的卸载,不是对象实例的释放。

相关推荐

    Java中类的生命周期

    ### Java中类的生命周期 #### 一、Java虚拟机与程序生命周期 在深入了解Java中类的生命周期之前,我们首先需要了解Java虚拟机(JVM)及其生命周期的概念。 **1. Java虚拟机启动** 当我们通过`java`命令运行一个...

    通过代码实例解析JAVA类生命周期

    Java 类生命周期是指从类加载到内存到卸载出内存的过程,包括加载、验证、准备、初始化和卸载五个阶段。本文将通过一个具体的代码实例来详细解析这些阶段。 首先,让我们分析给定的代码: ```java public class ...

    详解java类命周期.doc

    ### 详解Java类的生命周期 #### 一、Java类生命周期概览 Java类的生命周期是指一个`.class`文件从被加载到最终卸载的过程。这一过程主要包括五个阶段:加载(Loading)、连接(Linking)、初始化(Initialization...

    Java虚拟机和Java程序的生命周期?

    Java程序的生命周期从类的加载开始,到程序结束为止。主要包括以下几个阶段: 1. **启动阶段**:启动Java虚拟机,创建主类的对象并调用其`main()`方法。 2. **运行阶段**:程序开始执行,包括类的加载、初始化、...

    java线程生命周期详细讲解

    Java多线程生命周期的讲解,很详细,希望能帮到大家

    Java中类的生命周期与java垃圾回收机制

    Java中类的生命周期与java垃圾回收机制

    详解java类的生命周期.doc

    ### 详解Java类的生命周期 #### 引言 在探讨Java类的生命周期之前,我们先简单回顾一下Java类从创建到销毁的过程。Java作为一种广泛使用的编程语言,其强大的功能背后离不开Java虚拟机(JVM)的支持。对于Java...

    Java中对象的生命周期 ..doc

    ### Java中对象的生命周期 #### 一、对象的生命周期概览 在Java中,对象的生命周期是指从对象被创建到最终被垃圾回收器回收这段时间。理解对象的生命周期对于有效地管理和优化Java应用程序至关重要。 #### 二、...

    java变量的生命周期与作用域

    Java 变量的生命周期和作用域是密切相关的,变量的生命周期可以分为三个阶段:定义、初始化和销毁,而作用域可以分为四种:方法作用域、块作用域、类作用域和实例作用域。同时,函数的概念与作用是实现代码的重用性...

    详解java类的生命周期

    本文详细讲述了一个java类自调入内存至被卸载的整个声明周期,对理解对象的生命周期,jvm中的类加载等内容有所帮助。

    Java中类的生命周期.doc

    ### Java中类的生命周期 #### 一、概述 在Java编程语言中,类的生命周期是从类被加载到Java虚拟机(JVM)中开始,经过一系列处理直至类被卸载的过程。这一过程中涉及的关键步骤包括类的加载、连接、初始化等。理解...

    Java线程生命周期.zip

    Java线程生命周期是Java编程中的核心概念,它关乎程序的并发执行和性能优化。线程在Java中扮演着至关重要的角色,特别是在多任务处理和实时系统中。理解线程的生命周期有助于开发者更有效地管理和控制程序运行流程。...

    Java对象生命周期管理.pdf

    Java对象生命周期管理是Java开发中不可或缺的一个重要环节。在Java编程中,对象的创建、使用和销毁是由垃圾收集器自动管理的。理解这一过程对于优化应用程序性能至关重要,因为不恰当的对象管理可能导致内存泄漏,...

    深入java虚拟机(三)——类的生命周期(下)类的初始化1

    【深入Java虚拟机(三)——类的生命周期(下)类的初始化1】 类的生命周期在Java中是一个关键的概念,它涵盖了从加载到卸载的整个过程。在类的生命周期中,初始化阶段是非常重要的,因为它涉及到类的静态变量的赋值...

    spring bean的生命周期

    Spring Bean的生命周期是Spring框架中的核心概念,它涵盖了Bean从创建到销毁的全过程。了解这一过程对于优化应用程序的性能和管理资源至关重要。在Spring中,Bean的生命周期主要分为以下几个阶段: 1. **初始化阶段...

    深入java虚拟机(二)——类的生命周期(上)类的加载和连接1

    【深入Java虚拟机(二)——类的生命周期(上)类的加载和连接】 Java虚拟机(JVM)是Java程序的核心,它负责解释和执行Java字节码。类的生命周期在JVM中是一个关键的概念,它涵盖了从类的加载到卸载的整个过程。...

    Web编程(Java )-Servlet的生命周期.doc

    总结来说,Servlet的生命周期包括从类加载、实例化、初始化到提供服务,最后销毁的整个过程。通过实验,我们可以直观地理解这个过程,掌握Servlet的基本工作原理和使用方法。在实际开发中,理解Servlet生命周期有助...

Global site tag (gtag.js) - Google Analytics