java类加载

java中类的生命周期。

java类的生命周期:一个.class文件从加载到卸载的全过程。

过程包含:加载,连接,初始化,使用(类对象的生命周期。),卸载。

加载阶段:

1.找到需要加载的类并把类的信息加载到JVM的方法区

2.然后在堆中实例化一个java.lang.Class对象,作为方法区中这个类的信息入口。(反射)

类的加载方式比较灵活,我们最常用的加载方式有两种,

一种是根据类的全路径名找到相应的class文件,然后从class文件中读取文件内容;

另一种是从jar文件中读取。    


    加载阶段是类的生命周期中的第一个阶段,加载阶段之后,是连接阶段。有一点需要注意,就是有时连接阶段并不会等加载阶段完全完成之后才开始,而是交叉进行,可能一个类只加载了一部分之后,连接阶段就已经开始了。但是这两个阶段总的开始时间和完成时间总是固定的:加载阶段总是在连接阶段之前开始,连接阶段总是在加载阶段完成之后完成。


连接阶段:

连接阶段比较复杂,一般会跟加载阶段和初始化阶段交叉进行,这个阶段的主要任务就是做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步骤:验证、准备和解析。

验证:当一个类被加载之后,必须要验证一下这个类是否合法,比如这个类是不是符合字节码的格式、变量与方法是不是有重复、数据类型是不是有效、继承与实现是否合乎标准等等。总之,这个阶段的目的就是保证加载的类是能够被jvm所运行。

准备 :准备阶段的工作就是为类的静态变量分配内存并设为jvm默认的初值,对于非静态的变量,则不会为它们分配内存。有一点需要注意,这时候,静态变量的初值为jvm默认的初值,而不是我们在程序中设定的初值。jvm默认的初值是这样的:
基本类型(int、long、short、char、byte、boolean、float、double)的默认值为0。
引用类型的默认值为null。

常量的默认值为我们程序中设定的值,比如我们在程序中定义final static int a = 100,则准备阶段中a的初值就是100。

解析:这一阶段的任务就是把常量池中的符号引用转换为直接引用。那么什么是符号引用,什么又是直接引用呢?我们来举个例子:我们要找一个人,我们现有的信息是这个人的身份证号是1234567890。只有这个信息我们显然找不到这个人,但是通过公安局的身份系统,我们输入1234567890这个号之后,就会得到它的全部信息:比如湖北省武汉市武汉大学张三,通过这个信息我们就能找到这个人了。这里,123456790就好比是一个符号引用,而湖北省武汉市武汉大学张三就是直接引用。在内存中也是一样,比如我们要在内存中找一个类里面的一个叫做show的方法,显然是找不到。但是在解析阶段,jvm就会把show这个名字转换为指向方法区的的一块内存地址,比如c17164,通过c17164就可以找到show这个方法具体分配在内存的哪一个区域了。这里show就是符号引用,而c17164就是直接引用。在解析阶段,jvm会将所有的类或接口名、字段名、方法名转换为具体的内存地址。

初始化阶段:

在初始化阶段,JAVA虚拟机执行类的初始化语句,为类的静态变量赋予初始值。在程序中,静态变量的初始化有两种途径:
1、在静态变量的声明处进行初始化
2、在静态代码块中进行初始化。

[java]  view plain copy
  1. public class InitClass{  
  2.     public static String a = “nihao”;      //静态变量的声明处进行初始化  
  3.   
  4.     static {                                               //在静态代码块中进行初始化。  
  5.         System.out.println("初始化InitClass");  
  6.     }  
  7.     }  
静态变量的声明语句,以及静态代码块都被看做类的初始化语句,java虚拟机会按照初始化语句在文件中的 先后顺序 来依次执行他们。
如果有父类,则首先按照顺序运行父类中的变量赋值语句和静态语句。 

在类的初始化阶段,只会初始化与类相关的赋值语句和静态语句,也就是 有static关键字修饰的信息 ,没有static修饰的赋值语句和静态语句在实例化对象的时候才会运行。


使用阶段:


当类初始化完成后,根据类信息在堆区中实例化类对象,初始化非静态变量、非静态代码以及默认构造方法, 

创建对象 
对象的使用 
清除对象 


创建对象 
    通过创建一个对象可创建类的一个实例, 也称实例化此类。


例Rectangle rect = new Rectangle();

创建一个对象包括三部分:
      声名部分
      实例化部分 
      初始化部分


1、对象声明并不创建新的对象。 
例:
Rectangle rect;
2、实例化对象 
    操作符new通过为新对象分配存储空间来实例化类
    格式: new     类的构造方法
例          new Rectangle(100, 200);
              Rectangle rect = new Rectangle(100, 200);
3、初始化对象
    每个类都至少有一个构造函数,当创建对象时调用指定的构造函数来初始化对象

Rectangle rect = new Rectangle();
Rectangle rect = new Rectangle(100, 200);
在定义类时如未定义构造函数系统,java会自动构造一个没有参数的构造函数。

对象的使用
使用对象包括:
    从对象中获得信息 
    改变对象的状态 
    使对象执行某些操作 

实现途径:
    引用对象的变量
    调用对象的方法 

引用对象变量的格式:
            对象引用.对象的变量

SubInitClass2 aClass2=new SubInitClass2();
int b=aClass2.num;


调用对象的方法 
格式:  对象引用.对象方法名();
        或  对象引用.对象方法名(参数表);


Field2 field2=new Field2();
field2.Method();

卸载阶段:

java运行使系统有一个垃圾回收进程负责清除不再使用的对象

在类使用完之后,如果有下面的情况,类就会被卸载:
该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例。
 
加载该类的ClassLoader已经被回收。 

该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的方法。

如果以上三个条件全部满足,jvm就会在方法区垃圾回收的时候对类进行卸载,类的卸载过程其实就是在方法区中清空类信息,java类的整个生命周期就结束了。

结语:

1、 一个java类的完整的生命周期会经历加载、连接、初始化、使用(即对象生命周期)、和卸载五个阶段
2、加载:找到需要加载的类并把类的信息加载到jvm的方法区中,然后在堆区中实例化一个java.lang.Class对象,作为方法区中这个类的信息的入口。
3、连接:主要任务就是做一些加载后的验证工作以及一些初始化前的准备工作,可以细分为三个步骤:验证、准备和解析。
4、初始化: JAVA虚拟机执行类的初始化语句,为类的静态变量赋予初始值
5、使用:对象的生命周期(创建对象 、对象的使用 、清除对象 )
6、卸载、类使用完之后,如果有下面的情况,类就会被卸载:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值