Java类加载器:坑爹是我的特色

Java技术迷

共 2210字,需浏览 5分钟

 · 2021-05-19

来源 | 程序猿阿星(ID:cxyax1993

今天的主角是「在日常开发中,存在感非常低的类加载器」,众所周知大佬除了头发比较少,还非常低调,如果想和大佬交朋友,那一定要先认识大佬,下面阿星来带大家认识一下类加载器(本文不涉及源码)。

什么是类加载器

我们平时写了那么多的Java代码,却不知Java类的加载过程,岂不是很尴尬,为了打破尴尬,阿星得从Java类说起。

我们编写的Java类也就是.java文件,通过Java编译器编译成.class文件,.class文件中保存着Java代码转换后的虚拟机指令。

当程序使用某个Java类时,JVM虚拟机会加载它的.class文件到虚拟机的内存中,负责加载工作的就是类加载器

类加载过程

其实类加载器和日常生活中坐地铁过安检是一样的道理,不信你看下面的图

安检要经过一系列的检查过程,目的是让进入地铁站的人群符合乘坐标准,比如你不能感冒,不能带威胁人生安全的物品等。

同样类加载也要经过一系列检查过程,这个过程称为类加载过程

类加载过程分为加载、验证、准备、解析、初始化,下图是对类加载过程简单的介绍。

类加载过程不是本文的重点,如果对这块有兴趣深入研究的伙伴可以去自行百度或google。

下面要说说本文的重点,双亲委派模式

实力坑爹

双亲委派机制有点像实力坑爹,出了什么事情都让爹去擦屁股,爹解决不了,自己才承担。

JVM虚拟机提供了3种类加载器,它们分别是启动类加载器(Bootstrap)、扩展类加载器(Extension)、系统类加载器(System)。

每个类加载器都有明确的加载范围:

  • 启动类加载器(Bootstrap):加载<JAVA_HOME>/lib路径下的核心类库

  • 扩展类加载器(Extension):加载<JAVA_HOME>/lib/extl路径下的

  • 系统类加载器(System):加载系统类路径classpath,也就是我们经常用到的classpath路径,一般情况该类加载器是程序中默认的类加载器

双亲委派模式的原理也十分简单,类加载器收到类加载请求,会委托给父类加载器去执行,父类加载器还存在其父类加载器,则进一步向上委托,依次递归,直到顶层类加载器,如果顶层类加载器加载到该类,就成功返回class对象,否则委托给下级类加载器去执行,依次递归(此处的父子关系并非通常所说的继承关系,而是采用组合关系来实现)。

用大白话来说就是,每个儿子都很懒,有事就丢给爹去干,直到爹说这件事我也干不了,儿子自己再想办法完成。

双亲委派模式是为了避免重复加载和核心类篡改。

特殊需求

在日常开发中,我们可能会有特殊的业务需求,可能就需要使用到自定义类加载器,该加载器的上级一定是系统类加载器

你们想要的特殊需求

  • 资源隔离
    • web容器可能需要部署两个应用程序,不同的应用程序可能会依赖同一个第三方类库的不同版本,因此要保证每个应用程序的类库都是独立的,相互隔离
    • web容器有自己依赖的类库,不能与应用程序的类库混淆,基于安全考虑,应该让容器的类库和程序的类库隔离
  • 加密保护
    • 公司的一些核心类库,可能会把字节码加密,这样加载类的时候就必须对字节码进行解密
  • 其他来源加载类
    • 字节码是放在数据库、硬盘其他路径、甚至是在云端
  • 类重新加载
    • JVM中类对象的唯一性:类加载器实例+完整类名
    • 程序运行中,类内容发生变化,创建自定义加载器实例重新加载类,达到的热部署效果。

这里大家有个概念,理解下就够了,想深入探索就需要涉及源码分析,如果大伙有兴趣,评论区留言,阿星后续单独补一篇源码分析~

强大的父亲

有些爹的实力恐怖如斯,为了啥事都能帮后代处理好,直接破坏双亲委派模式,深受孩儿们的喜爱。

Java应用中存在着很多服务提供者接口(Service Provider Interface,SPI),这些接口允许第三方为它们提供实现,如常见的SPIJDBC、JNDI等,这些SPI的接口属于Java核心库,一般存在rt.jar包中,由启动类加载器(Bootstrap)加载,而SPI的第三方实现代码则是作为Java应用所依赖的jar包被存放在classpath路径下。

由于SPI接口中的代码需要加载第三方实现类并调用其相关函数,但SPI的核心接口类是由启动类加载器(Bootstrap)加载的,Bootstrap加载器无法直接加载SPI的实现类。

在这种情况下,我们就需要一种特殊的类加载器来加载第三方的类库,它就是线程上下文类加载器,线程的上下文类加载器默认设置的就是系统类加载器(System)。

1、Intellij IDEA这样 配置注释模板,让你瞬间高出一个逼格!
2、吊炸天的 Docker 图形化工具 Portainer,必须推荐给你!
3、最牛逼的 Java 日志框架,性能无敌,横扫所有对手!
4、把Redis当作队列来用,真的合适吗?
5、惊呆了,Spring Boot居然这么耗内存!你知道吗?
6、全网最全 Java 日志框架适配方案!还有谁不会?
7、Spring中毒太深,离开Spring我居然连最基本的接口都不会写了

点分享

点收藏

点点赞

点在看

浏览 10
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报