类加载器及双亲委派机制

目录

类加载的过程

加载

链接

初始化

类加载器

类加载器分类

启动类加载器(Boostrap Classloader)

扩展类加载器(Extension Class Loader)

应用类加载器(Application Class Loader)

双亲委派机制

优点


类加载的过程

        类的加载过程有5个步骤:加载->验证->准备->解析–>初始化

加载

        1.通过一个类的全限定名获取定义此类的二进制字节流

        2.将这个字节流代表的静态存储结构转化为方法区运行时结构

        3.在内存中生成一个代表这个类的Class对象,作为方法区这个类的各种数据的访问入口

链接

  链接阶段包含三个步骤:

        1.验证:目的在于确保Class文件的字节流中包含信息是否符合当前虚拟机的要求,保证被加载类的正确性,不会危害虚拟机自身的安全,主要包括四种验证,文件格式验证,元数据验证,字节码验证,符号引用验证。

        2.准备:为类变量分配内存并设置该类变量的默认初始值。不包含用final修饰的static变量,因为final在编译的时候就会分配类,准备阶段会显式地初始化。

        3.解析:将常量池内的符号引用转换为直接引用过程。

初始化

        初始化阶段就是执行类构造器方法()的过程


类加载器

类加载器分类

  • 站在java虚拟机的角度看,JVM支持两种加载器,分别为启动类加载器(BootstrapClassLoader)和自定义类加载器。
  • 从概念上来说自定义加载器一般是程序中由开发人员定义的一类加载器。
  • 然而java虚拟机规范中并没有这样定义,而是将所有派生于抽象类ClassLoader的类加载器都划分为自定义加载器。

  一般来说在java8以及以前的版本都会用到如下三种加载器:

  • 启动类加载器(Bootstrap Class Loader)
  • 扩展类加载器(Extension Class Loader)
  • 应用类(系统类)加载器(Application Class Loader)

启动类加载器(Boostrap Classloader)

        这个类加载使用C/C++语言实现的,嵌套在JVM内部,它用来加载Java的核心库((JAVA_HOME/jre/lib/rt.jar、resources.jar或sun.boot.class.path路径下的内容),用于提供JVM自身需要的类,出于安全考虑,Boostrap启动类加载器只加载包名为java、javax、sun等开头的类

扩展类加载器(Extension Class Loader)

        使用java语言编写,独立于虚拟机,派生于Classloader,其父类加载器为启动类加载器,主要负责加载核心类库以外的扩展类。

应用类加载器(Application Class Loader)

        使用java语言编写,父类加载器为扩展类加载器,该类加载是程序中默认的类加载器,一般来说,java应用的类都是由它来完成加载。因为该加载器是ClassLoader类中的getSystemClassLoader()方法的返回值,所以一般也称为该加载器为系统类加载器。该加载器主要是加载用户类路径上所有的类库,如果应用程序中没有定义过自己的类加载器,一般情况下这个就是程序的默认加载器。

类加载器及双亲委派机制_第1张图片

类加载器及双亲委派机制_第2张图片

 

双亲委派机制

        1.如果一个类加载器收到了类加载请求,它不会自己先去加载,而是把这个请求委托给父类的加载器去执行

        2.如果父类加载器还存在父类加载器,则进一步向上委托,依次递归,请求最终将到达顶层的启动类加载器

        3.如果父类加载器可以完成类加载,就成功返回,否则会抛出异常,交给子类加载器尝试去自己加载

举个例子:
        大家所熟知的Object类,直接告诉大家,Object默认情况下是启动类加载器进行加载的。假设我也自定义一个Object,并且制定加载器为自定义加载器。现在你会发现自定义的Object可以正常编译,但是永远无法被加载运行。
        这是因为申请自定义Object加载时,总是启动类加载器,而不是自定义加载器,也不会是其他的加载器。

类加载器及双亲委派机制_第3张图片

 

优点

  1. 避免了类的重复加载
  2. 保护了程序的安全性,防止核心的API被修改

你可能感兴趣的:(JVM,java,jvm,开发语言)