我的面试经之JVM(二)类加载器的分类

·JVM支持两种类型的类加载器:分别为引导类加载器(Bootstrap ClassLoader)自定义类加载器(User-Defined ClassLoader)
·从概念上来讲,自定义类加载器一般指开发人员自定义类的加载器,但是JVM规范是将所有派生于抽像类ClassLoader的类加载器都是自定义类加载器 

·不论加载器类型如何划分,在程序中我们最常见的只有三个:引导类加载器、扩展类加载器·、系统类加载器

 

 

这四者是包含关系不是上下层关系,也不是继承关系。

 

 只有BootStrap是C和C++写的,其他的是Java语言写的

扩展类加载器和系统类加载器都间接继承ClassLoader

 

 

 

实例图:

 

 

 

结论:  系统类加载器的上层是扩展类加载器,扩展类加载器的上层是引导类加载器

     Java核心类库用引导类加载器加载,用户自定义类加载器,默认使用系统类加载器。 

 

 

 

 

   启动类加载器(引导类加载器Bootstrap ClassLoader):

      由C/C++实现,嵌套在JVM内部

      用来加载Java的核心库(JAVA_ HOME/jre/lib/rt.jar、resources . jar或sun . boot . class. path路径下的内容) , 用于提供JVM自身需要的类

      并不继承自java.lang.ClassLoader,没有父类加载器

      加载扩展类和应用程序类加载器,并指定为他们的父类加载器

      出于安全考虑BootStrap只加载包名为java、javax、sun开头的类

结果:

 

 

 

 

 

 

 

 

  扩展类加载器(Extension ClassLoader)

      Java语言编写,由sun.misc.Launcher$ExtClassLoader内部类实现

      派生于ClassLoader类

      父类加载器为启动类加载器

      从java. ext .dirs系统属性所指定的目录中加载类库,或从JDK的安装目录的jre/lib/ext子目录(扩展目录)下加载类库如果用户创建的JAR放在此目录下,也会自动由扩展类加载器加载。

 

结果:

 

 

 

 

 

  应用程序类加载器(系统类加载器 AppClassLoader)

      Java语言编写,由sun.misc.Launcher$ExtClassLoader内部类实现

      派生于ClassLoader类

      父类加载器为扩展类加载器

      负责从环境变量classpath或系统属性 java.class.path指定路径下的类库

      该类是程序中默认的类加载器,一般来说,Java应用的类都由它完成

      通过ClassLoader #getSystemClassLoader ()方法可以获取到该类加载器

 

 

  用户自定义类加载器

      在Java的日常应用程序开发中,类的加载几乎是由上述3种类加载器相互配合执行的,在必要时,我们还可以自定义类加载器,来定制类的加载方式。

    为什么要有用户自定义类加载器

        隔离加载器类(用到中间件)

        修改类加载的方式

        扩展加载源

        防止源码泄露

 

  用户自定义类加载器实现步骤

      1.开发人员可以通过继承抽象类java. lang.ClassLoader类的方式,实现自己的类加载器,以满足一些特殊的需求

      2.在JDK1.2之前,在自定义类加载器时,总会去继承ClassLoader类并重写loadClass()方法,从而实现自定义的类加载类,但是在JDK1.2之后已不再建议用户去覆盖loadClass()方法,

        而是建议把自定义的类加载逻辑写在findClass()方法中     

      3.在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类,这样就可以避免自己去编写findClass()方法及其获取字节码流的方式,

        使自定义类加载器编写更加简洁。

 

 

 

posted @ 2020-03-10 20:11  Timeouting  阅读(284)  评论(0编辑  收藏  举报