类的加载机制 (一)

      做为的学习笔记,类的加载机制主要从类的加载,连接,以及初始化 ,类加载器除了根类加载器之外,其他类加载器都是用java编写的,所以我们程序员可以开发自己的类加载器,通过使用自定义类加载器,可以完成一些特定的功能。

  1 jvm 和类的认识

         当我们通过java命令运行java程序时,这个命令就会启动一个java虚拟机进程,我们的java程序就处于这个进程中,java程序中的所有线程,所有变量都处于jvm的同一个进程里,它们都使用该jvm进程的内存区。

     当系统出现一下情况时,jvm进程将被终止

      》程序运行到最后正常结束

      》程序所在平台强制结束了jvm进程

      》 程序执行过程中遇到未捕获的异常或者错误而结束

      》 程序运行到使用System.exit() 或者Runtime.getRuntime().exit()代码处结束程序

java程序结束,jvm进程结束,该进程在内存中的状态将会失去,下面举例子说明:

     &  首先创建一个静态变量 q  

public class TestQ {
   //定义一个静态变量
	public static int q = 4;
}

    & 定义一个测试类 创建TestQ实例,并访问该实例的静态变量q  

public class TestTQ {
   public static void main(String[] args) {
	 TestQ  t = new TestQ();
	 t.q++;
	 System.out.println(t.q);
    }
}

 & 创建第二测试类 并访问类变量q

public static void main(String[] args) {
	   TestQ t2 = new TestQ();
	   System.out.println(t2.q);
	}
}

      我们首先运行第一个测试类 访问q 自增了1  程序给出的结果是5 相信大家对这个结果没有什么疑问把,而我们再来运行第二个测试类的结果是多少呢,依然是4 ,为什么呢? 原因是两次运行java程序处于2个不同的jvm进程中,第一次运行jvm结束后,它对q所做的修改将全部失去,两个jvm之间不会共享数据。

2 类的加载

    类的加载: 当程序主动使用 一个类时 ,如果该类没有被加载时,则jvm会通过 加载  连接 初始化三个步逐来对类进行初始化操作 ,三个操作一次完成,把这三个步逐统称为类加载或类初始化,类加载就是将类的class文件读入内存,并为之创建一个java.lang.Class对象 。

     类的加载又类加载器完成的,类加载器通常是由jvm提供,这些类加载器也是程序运行的基础,类加载器分为2类,一是jvm提供的系统类加载器,另一个是 开发者可以通过继承ClassLoader基类来创建自己的类加载器,

      通过使用不同的类加载器。可以从不同来源加载类的二进制数据,通常有如下几种来源:

     》 从本地系统文件加载class文件

     》从jar包加载class文件

     》通过网络加载class 文件

     》把一个java 源文件动态编译,并执行加载

类的加载不一定都是在”第一次使用“ 才进行加载,java虚拟机规范允许系统预先加载一些类。

3 类的连接

      当类被加载了之后,系统会为之生成一个对应的class对象,接着将会进入连接阶段,连接阶段负责把类的二进制数据合并到jre中,而类的连接又分为三个阶段

    》 验证: 验证阶段用于检测被加载的类是否又正确的内部结构,并且和其他类协调一致

    》 准备 :类准备阶段则负责为类变量分配内存,并设置默认初始值

    》 解析:将类的二进制数据中的符号引用替换成直接引用

4 类的初始化

   虚拟机负责对类进行初始化,主要就是对类变量进行初始化,在java类中对类变量指定初始值有2种方式:1是 声明变量时指定初始值  2是 使用静态初始化块为类变量指定初始值  静态初始化块都将被当成类的初始化语句,jvm会按照这些语句在程序中的排序顺序依次执行它们。

public class Test01 {
  static{
	  int b = 8;
	  System.out.println("-------");
  }
     static int a = 3;
     static int b = 12;
     static int c;
     public static void main(String[] args) {
		System.out.println(Test01.b);
		System.out.println(Test01.c);
	}
}

  其中b的值为12 ,c 的值为0 ,b在第二次赋值会把其中的值替换掉,没有赋予值的int 类型,默认值为0。

    jvm 初始化一个类包含如下几个步逐

 》 如果这个类还没有被加载和连接。则程序先加载并且连接该类

 》 如果该类的直接父类还没有被初始化,则先初始化其直接父类(jvm 最先初始化的总是java.lang.Object类)

 》如果类中有初始化语句,则系统一次执行这些初始化语句

当程序主动使用一个类时,系统会保证该类以及所用父类都会被初始化。

5 类初始化的时机

 》 调用一个类的静态方法

》访问一个类或接口的类变量,或为类变量赋值

 》 使用反射方式来强制创建一个类或者接口对应的java.lang.Class对象 (Class.forName("Person"))

》初始化一个类的子类

》直接使用java.exe命令来运行一主类  程序先初始化主类

 

 

 

   

                                                                                                                                                                                                                                                                                                                                                    

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章