这次彻底搞懂类加载器吧!!!

一、类加载过程

  • 类加载过程分为:加载->链接->初始化

  • 链接过程具体细分为:验证->准备->解析

二、类加载器

1、定义

类加载器是一个加载类的对象,它工作在类加载过程中的加载这一步,通过类的全类名获得该类的二进制字节流然后加载到JVM;每个类都会有一个引用指向加载它的类加载器。(注:数组类不是类加载器加载的,因为它没有对应的二进制字节流,它直接由JVM生成。)

2、作用

将Java源程序(.java文件)编译生成的字节码文件(.class文件)通过全类名加载到JVM中,也就是在内存中生成一个代表该类的Class对象;类加载器也可以加载文本、图片、配置文件等资源。

3、加载规则

JVM启动的时候不会一次性将所有的类都进行加载,而是在程序执行的过程中按需加载,这种加载方式对内存更加友好。(注:Spring中的Bean对象交给IOC容器管理后,IOC并不会立即加载类并创建对象,也是在有需要依赖注入的时候才去容器中查找,如果没有才开始加载并创建。)

类加载器加载每个类后都会进行记录,并且在加载前会先根据记录判断这个类是否已经被加载;如果被加载则直接返回,否则尝试加载;所以对于一个类加载器来说,同一个类只会被加载一次。

三、JVM中的内置类加载器

  • 启动类加载器:最顶层的类加载器,由C++实现,没有父类加载器;用于加载JDK内部的核心类库和-Xbootclasspath参数指定路径下的类。

  • 扩展类加载器:用于加载%JRE_HOME%/lib/ext目录下的jar包和类。

  • 应用类加载器:用于加载当前应用classpath下的jar包和类。

只有启动类加载器是JVM内部实现的,其它的类加载器都是在JVM外部实现的,并且都继承了ClassLoader抽象类。这样设计的好处是可以让用户去自己定义类加载器,方便应用程序自己决定如何获取需要的类。

四、自定义类加载器

自定义类加载器要继承ClassLoader抽象类,该类有两个重要方法。

  • loadClass(String name, boolean resolve) 实现了双亲委派机制,name为类的二进制名称,resolve决定是否在加载时调用resolveClass(Class<?> c) 方法解析该类。

  • findClass(String name) 根据类的二进制名称查找类,默认实现为空。

自定义类加载器时如果想打破双亲委派机制则重写loadClass()方法即可;如果不想打破则重写findClass()方法,当类不能被父类加载器加载时,最终会通过自定义类加载器的该方法加载。

五、双亲委派机制

ClassLoader类使用委托机制来加载类;除启动类加载器外,每个ClassLoader实例都有一个父类加载器;当需要加载类时,ClassLoader实例会在亲自加载类前,将加载类的任务委托给父类加载器,直到委托到启动类加载器,然后才开始尝试去加载类。

1、执行流程
  • 在类加载时,类加载器会先判断当前类是否被加载,如果被加载则直接返回,否则将请求委托给父类加载器去加载,每个类加载器都会走这样的流程;所以,最终请求会委托到顶层的启动类加载器中。

  • 启动类加载器开始尝试加载这个类,如果不能加载该类再交给子类加载器进行加载,如果类一直未加载成功,最终会交给最下层的类加载器。

  • 如果下层的类加载器也无法加载这个类,那么它就会抛出一个 ClassNotFoundException 异常。

2、使用好处

双亲委派机制保证程序的稳定运行,避免同一个类的重复加载,也保证了Java的核心API不被外部修改。(注:JVM 判断不同类的方法是类名和加载该类的类加载器,如果同一个类文件被两个不同的类加载器加载产生的是两个不同的类。)

不使用双亲委派机制时,类加载器加载类时会出现一些问题,比如自己写一个全类名为java.lang.String的类时,那么程序运行的时候就会出现两个不同的String类。双亲委派机制可以保证加载的是JDK里的那个 String类,而不是自己写的String类。

因为应用类加载器在加载自己写的 String类时,会委托给扩展类加载器去加载,而扩展类加载器又会委托给启动类加载器,启动类加载器发现已经加载过了String类,会直接返回,不会再去加载自己写的String类进而导致程序出现异常。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值