java类的加载机制

来源:互联网 发布:剑灵天族御姐捏脸数据 编辑:程序博客网 时间:2024/06/14 08:13

Java类的加载机制

1.类的加载,连接和初始化

1.1 JVM和类

  • Java虚拟机是可运行JAVA代码的假想计算机.
  • Java源文件通过编译器,能够产生相应的.class文件,也就是字节码文件,而字节码文件又通过Java虚拟机中的解释器(java虚拟机指令集)编译成特定机器上的机器码。
  • Java源文件—->编译器—->字节码文件
  • 字节码文件—->jvm—->机器码

当调用Java命令运行某个Java程序时,该命令将会启动一个Java虚拟机进程,不管该程序有多么复杂,该程序启动了多少个线程,他们都处于该Java虚拟机进程里。同一个JVM的所有线程,所有变量都处于同一个进程里,它们都使用该JVM的内存区,当系统出现以下几种情况时,JVM进程会被终止。

  • 程序运行到最后正常结束
  • 程序运行到使用System.exit()或Runtime.getRuntime().exit()代码结束程序。
  • 程序执行过程中遇到未捕获的异常或错误而结束。
  • 程序所在平台强制结束JVM进程。
public class A{  public static int a = 6;}public class Test1{   public static void mian(String[] args){        A a = new A();        a.a++;        System.out.println(a.a);        //输出结果为7    }}public class Test2{   public static void mian(String[] args){        A a = new A();        System.out.println(a.a);        //输出结果为6    }}

两次运行Java程序处于两个不同的JVM进程中,两个JVM之间不会共享数据。

1.2 类的加载

当程序主动使用某一个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三个步骤来对该类进行初始化。类加载指的是将类的class文件读入内存,并为之创建一个java.lang.Class对象。类加载器通常由JVM提供,通过使用不同的类加载器,可以从不同来源加载类的二进制文件。

  • 本地文件系统加载class文件
  • JAR包加载class文件
  • 通过网络加载class文件
  • 把一个Java源文件动态编译,并执行加载

1.3 类的连接

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

  • 验证:验证阶段用于检验被加载的类是否正确的内部结构,并和其他类协调一致。
  • 准备:类准备阶段则负责为类的变量分配内存,并设置默认初始值。
  • 解析:将类的二进制数据中的符号引用替换成直接引用。

1.4类的初始化

在类的初始化阶段,虚拟机负责对类进行初始化,主要就是对类变量进行初始化,在java类中对类变量指定初始值有两种方式。
- 声明变量时指定初始值
- 使用静态初始化块为类变量指定初始值

1.5 类的初始化时机

  • 创建类实例
  • 调用某个类的静态方法
  • 访问某个类的变量
  • 初始化某个类有父类时,该类的所有父类都要初始化
  • 直接使用java.exe命令来运行某个类
  • 使用反射方式来强制创建某个类或接口对应的java.lang.Class对象

2 类加载器

2.1 类加载器简介

类加载器负责将.calss文件加载到内存中,并为之生成对应的java.lang.Class对象。一旦一个类被载入JVM中,同一个类就不会被再次载入了。一个类的全限定类名和其类加载器作为其唯一标识。当JVM启动时,会形成由三个类加载器组成的初始类加载器。

  • Bootstrap ClassLoader:
    根类加载器,它负责加载Java的核心类,他非常特殊,它并不是java.lang.ClassLoader的子类,而是JVM自身实现的。
  • Extension ClassLoader:
    扩展类加载器,它负责加载JRE的扩展目录(jre/lib/ext)
  • System ClassLoader:
    系统类加载器,它负责加载来自java命令的-classpath选项,java.class.path系统属性,或者CLASSPATH环境变量所指定的JAR包和类路径。

2.2 类加载机制

JVM的类加载机制主要有如下三种
- 全盘负责:
所谓全盘负责,就是当一个类加载器负责加载某个Class时,该Class所依赖的和引用的其他Class也将由该类加载器负责载入,除非显式使用另外一个类加载器来载入。
- 父类委托:
所谓父类委托,则是先让parent(父)类加载器视图加载该Class,只有在父类加器无法加载该类时才尝试从自己的路径中加载该类。
- 缓存机制:
缓存机制将会保证所有加载过的Class都会被缓存,当程序中需要使用某个Class时,类加载器先从缓冲区中搜索该Class,只有当缓存区中不存在该Class对象时,系统才会读取该类对应的二进制数据,并将起转成Class对象,存入缓冲区中。这就是为什么修改了Class后,必须重新启动JVM,程序所做的修改才会生效的原因。