深入浅出JVM(八)之类加载器

 本篇文章将重点聊聊类加载器,围绕类加载器深入浅出的解析类加载器的分类、种类、双亲委派模型以及从源码方面推导出我们的结论

类加载器简介

什么是类加载器?

类加载器通过类的全限定类名进行类加载机制从而生成Class对象

Class对象中包含该类相关类信息,通过Class对象能够使用反射在运行时阶段动态做一些事情

显示加载与隐式加载

类加载器有两种方式进行加载,一种是在代码层面显示的调用,另一种是当程序遇到创建对象等命令时自行判断该类是否进行过加载,未加载就先进行类加载

显示加载:显示调用ClassLoader加载class对象

隐式加载:不显示调用ClassLoader加载class对象(因为虚拟机会在第一次使用到某个类时自动加载这个类)

 //显示类加载  第7章虚拟机类加载机制.User为全限定类名(包名+类名)
 Class.forName("第7章虚拟机类加载机制.User");
             
 //隐式类加载
 new User();    

唯一性与命名空间

判断两个类是否完全相同可能并不是我们自认为理解的那样,类在JVM中的唯一性需要根据类本身和加载它的类加载器

  • 唯一性

    • 所有类都由它本身和加载它的那个类在JVM中确定唯一性
    • 也就是说判断俩个类是否为同一个类时,如果它们的类加载器都不同那肯定不是同一个类
  • 命名空间

    • 每个类加载有自己的命名空间,命名空间由所有父类加载器和该加载器所加载的类组成
    • 同一命名空间中,不存在类完整名相同的俩个类
    • 不同命名空间中,允许存在类完整名相同的俩个类(多个自定义类加载加载同一个类时,会在各个类加载器中生成对应的命名,且它们都不是同一个类)

基本特征

类加载器中有一些基本特性,比如子类加载器可以访问父类加载器所加载的类、父类加载过的类子类不再加载、双亲委派模型等

  • 可见性

    • 子类加载器可以访问父类加载器所加载的类*
    • (命名空间包含父类加载器加载的类)
  • 单一性

    • 因为可见性,所以父类加载器加载过的类,子类加载器不会再加载
    • 同一级的自定义类加载器可能都会加载同一个类,因为它们互不可见
  • 双亲委派模型

    • 由哪个类加载器来进行类加载的一套策略,后续会详细说明
类加载器分类

类加载器可以分成两种,一种是引导类由非Java语言实现的,另一种是由Java语言实现的自定义类加载器

  • 引导类加载器 (c/c++写的Bootstrap ClassLoader)
  • 自定义类加载器:由ClassLoader类派生的类加载器类(包括扩展类,系统类,程序员自定义加载器等)

系统(应用程序)类加载器和扩展类加载器是Launcher的内部类,它们间接实现了ClassLoader

注意

image-20210516203457475.png

平常说的系统(应用程序)类加载器的父类加载器是扩展类加载器,而扩展类加载器的父类加载器是启动类加载器,都是"逻辑"上的父类加载器

实际上扩展类加载器和系统(应用程序)类加载器间接继承的ClassLoader中有一个字段parent用来表示自己的逻辑父类加载器

类加载器种类
  • 启动(引导)类加载器

    • Bootstrap Classloader c++编写,无法直接获取
    • 加载核心库<JAVA_HOME>\lib\部分jar包
    • 不继承java.lang.ClassLoader,没有父类加载器
    • 加载扩展类加载器和应用程序类加载器,并指定为它们的父类加载器
  • 扩展类加载器

    • Extension Classloader
    • 加载扩展库<JAVA_HOME>\lib\ext*.jar
    • 间接继承java.lang.ClassLoader,父类加载器为启动类加载器
  • 应用程序(系统)类加载器

    • App(System) Classloader 最常用的加载器
    • 负责加载环境变量classpath或java.class.path指定路径下的类库 ,一般加载我们程序中自定义的类
    • 间接继承java.lang.ClassLoader,父类加载器为扩展类加载器
    • 使用ClassLoader.getSystemClassLoader()获得
  • 自定义类加载器(实现ClassLoader类,重写findClass方法)

通过代码来演示:

 public class TestClassLoader {
     public static void main(String[] args) {
         URL[] urLs = Launcher.getBootstrapClassPath().getURLs();
         /*
         启动类加载器能加载的api路径:
         file:/D:/Environment/jdk1.8.0_191/jre/lib/resources.jar
         file:/D:/Environment/jdk1.8.0_191/jre/lib/rt.jar
         file:/D:/Environment/jdk1.8.0_191/jre/lib/sunrsasign.jar
         file:/D:/Environment/jdk1.8.0_191/jre/lib/jsse.jar
         file:/D:/Environment/jdk1.8.0_191/jre/lib/jce.jar
         file:/D:/Environment/jdk1.8.0_191/jre/lib/charsets.jar
         
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值