【面试题精讲】JVM-打破双亲委派机制-线程上下文类加载器

简介: 【面试题精讲】JVM-打破双亲委派机制-线程上下文类加载器

1. 什么是线程上下文类加载器?

线程上下文类加载器(Thread Context ClassLoader)简称 TCCL,是 Java 中一个重要的概念,它是 Java 中的一个类加载器,用于加载线程上下文中所需要的类。其本质上是一个普通的 Java 类,不同之处在于其拓展了 ClassLoader 基础类,提供了一些特殊的功能。线程上下文类加载器和普通类加载器不同的是,它不需要遵循双亲委派机制。

2. 为什么需要线程上下文类加载器?

Java 应用程序中,类的加载是由类加载器完成的,按照双亲委派机制的规则,子类加载器会向父级类加载器请求加载,如果父级类加载器不能完成加载操作,则会将其沿上继续传递给更高级别的父级类加载器,最终如果找不到对应类加载器,则系统将会抛出 ClassNotFoundException 异常。双亲委派机制一方面可以保证 Java 平台核心类的安全性,另一方面也可以保证 Java 核心类库的稳定性和正确性。

但是,有时候我们希望某些类的加载不受双亲委派机制的限制,比如一些框架或者插件就需要自己实现一套类加载机制。这时候就需要线程上下文类加载器来打破双亲委派机制,使得父类加载器可以访问到子类加载器加载的类。

3. 线程上下文类加载器的实现原理

线程上下文类加载器代码实现非常简单,它的主要思想是在需要访问的类的加载器不同的时候,通过线程上下文类加载器来进行操作。

public class Demo {
    public static void main(String[] args) {
        ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(new MyClassLoader());
        // 执行操作
        Thread.currentThread().setContextClassLoader(oldClassLoader);
    }
}

在上面的代码中,我们首先获取了当前线程的上下文类加载器,然后将其重新设置成自定义的 MyClassLoader,执行一些需要访问不同类加载器的操作,最后需要将当前线程的上下文类加载器重新设置为原来的类加载器。

4. 线程上下文类加载器的使用示例

Java 中经典的线程上下文类加载器的案例就是 JDBC 规范。JDBC 规范中定义了一系列接口,这些接口通常由驱动程序提供实现。当 JDBC 的客户端在应用程序中加载驱动程序时,驱动程序的类加载器加载了具体的类,不同的数据库的驱动程序类在不同的类加载器中。

这样就可能出现了两种情况:

  1. 当前线程的类加载器为驱动程序类加载器,但是应用程序获取的数据库连接是由另一个类加载器加载的。
  2. 当前线程的类加载器为应用程序类加载器,但是驱动程序获取的数据库连接是由另一个类加载器加载的。

以上两种情况都会造成 ClassNotFoundException 异常。所以为了解决这种情况,JDBC 规范使用了线程上下文类加载器。

5. 线程上下文类加载器的优点

线程上下文类加载器解决了类加载机制中父子类加载器的限制,可以在不破坏双亲委派模型的基础上,允许线程在运行期间使用自己的加载器读取类库。

另外,线程上下文类加载器还可以增加程序的灵活性,在不同的容器中运行程序时,可以使用其特有的类加载器,加载不同环境需要的类,可以解决常见的 jar 冲突问题。

6. 线程上下文类加载器的缺点

线程上下文类加载器机制存在的问题主要是使用不当时降低性能的问题。如果不在必要的时候使用线程上下文类加载器,在获取类的时候会增大时间开销,因为是通过反射对类进行初始化的,这个操作需要一定的时间。

7. 线程上下文类加载器的使用注意事项

在线程中使用线程上下文类加载器时,需要注意以下几点:

  1. 在线程的运行期间,可以使用 setContextClassLoader()方法来设置线程上下文类加载器,线程结束后需要将其还原到原始类加载器,以免影响其他线程的正常运行。
  2. 如果在应用程序中使用自定义的类加载器,需要一些特殊的代码来隔离各个加载器。 在容器框架中,通常不需要直接操作线程上下文类加载器,而是使用如 Java 2 Platform Standard Edition(Edition)1.3.1 或更高版本中提供的 Thread.currentThread().getContextClassLoader()方法,将线程的上下文类加载器设置为当前线程的类加载器。

8. 总结

线程上下文类加载器是 Java 虚拟机提供的一个重要概念。其本质是一个 Java 类,用于加载线程上下文中所需要的类。它的作用是为了打破双亲委派机制,在某些情况下需要读取特定的类库或者线程需要使用特定的类库时,可以通过线程上下文类加载器实现。线程上下文类加载器有一些优点,比如可以对于同一份代码实现多次加载,以及解决不同类加载器的冲突等。但是,它也存在一些缺点,比如降低性能的问题。在使用线程上下文类加载器时,需要注意保存原始类加载器,并在合适的时候还原。同时,需要特别注意多个类加载器可能会导致冲突等问题,需要特别处理。

本文由 mdnice 多平台发布


相关文章
|
11月前
|
Arthas 存储 算法
深入理解JVM,包含字节码文件,内存结构,垃圾回收,类的声明周期,类加载器
JVM全称是Java Virtual Machine-Java虚拟机JVM作用:本质上是一个运行在计算机上的程序,职责是运行Java字节码文件,编译为机器码交由计算机运行类的生命周期概述:类的生命周期描述了一个类加载,使用,卸载的整个过类的生命周期阶段:类的声明周期主要分为五个阶段:加载->连接->初始化->使用->卸载,其中连接中分为三个小阶段验证->准备->解析类加载器的定义:JVM提供类加载器给Java程序去获取类和接口字节码数据类加载器的作用:类加载器接受字节码文件。
922 55
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
482 2
|
11月前
|
Arthas Java 测试技术
JVM深入原理(六)(一):JVM类加载器
目录6. JVM类加载器6.1. 类加载器-概述6.2. 类加载器-执行流程6.3. 类加载器-分类(JDK8)6.3.1. JVM底层实现的类加载器6.3.1.1. 启动类加载器6.3.2. Java代码实现类的加载器6.3.2.1. 扩展类加载器6.3.2.2. 应用程序类加载器6.4. 类加载器-Arthas查看类加载器
204 0
|
11月前
|
Java 关系型数据库 MySQL
JVM深入原理(六)(二):双亲委派机制
自定义类加载器打破双亲委派机制的方法:复写ClassLoader中的loadClass方法常见问题:要加载的类名如果是以java.开头,则会抛出安全性异常加载自定义的类都会有一个共同的父类Object,需要在代码中交由父类加载器去加载自定义类加载器不手动指定parent会默认指定应用类加载两个自定义类加载器加载同一个类会被认为是两个对象,只有相同的类加载器+想通的类限定名才会被认为是一个对象。
352 0
|
SQL 缓存 监控
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
本文详细解析了数据库、缓存、异步处理和Web性能优化四大策略,系统性能优化必知必备,大厂面试高频。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:4 大性能优化策略(数据库、SQL、JVM等)
|
存储 监控 算法
Java JVM 面试题
Java JVM(虚拟机)相关基础面试题
343 4
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
存储 算法 安全
JVM常见面试题(四):垃圾回收
堆区域划分,对象什么时候可以被垃圾器回收,如何定位垃圾——引用计数法、可达性分析算法,JVM垃圾回收算法——标记清除算法、标记整理算法、复制算法、分代回收算法;JVM垃圾回收器——串行、并行、CMS垃圾回收器、G1垃圾回收器;强引用、软引用、弱引用、虚引用
|
Arthas 监控 Java
JVM进阶调优系列(9)大厂面试官:内存溢出几种?能否现场演示一下?| 面试就那点事
本文介绍了JVM内存溢出(OOM)的四种类型:堆内存、栈内存、元数据区和直接内存溢出。每种类型通过示例代码演示了如何触发OOM,并分析了其原因。文章还提供了如何使用JVM命令工具(如jmap、jhat、GCeasy、Arthas等)分析和定位内存溢出问题的方法。最后,强调了合理设置JVM参数和及时回收内存的重要性。
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)

热门文章

最新文章