在线客服
扫描二维码
下载博学谷APP
扫描二维码
关注博学谷微信公众号
Java类隔离加载实现原理是什么? JVM 提供一个全局类加载器的设置接口,直接替换全局类加载器,但无法解决多个自定义类加载器同时存在的问题。然而JVM会选择当前类的类加载器来加载所有该类的引用的类。

类隔离技术是什么?
只要Java 代码写的足够多就一定会出现这种情况:系统新引入了一个中间件的 jar 包,编译的时候一切正常,一运行就报错:java.lang.NoSuchMethodError,然后就哼哧哼哧的开始找解决方法,最后在几百个依赖包里面找的眼睛都快瞎了才找到冲突的 jar,把问题解决之后就开始吐槽中间件为啥搞那么多不同版本的 jar,写代码五分钟,排包排了一整天。
上面这种情况就是Java 开发过程中常见的情况,原因也很简单,不同 jar 包依赖了某些通用 jar 包(如日志组件)的版本不一样,编译的时候没问题,到了运行时就会因为加载的类跟预期不符合导致报错。
举个例子:A 和 B 分别依赖了 C 的 v1 和 v2 版本,v2 版本的 Log 类比 v1 版本新增了 error 方法,现在工程里面同时引入了 A、B 两个 jar 包,以及 C 的 v0.1、v0.2 版本,打包的时候 maven 只能选择一个 C 的版本,假设选择了 v1 版本。到了运行的时候,默认情况下一个项目的所有类都是用同一个类加载器加载的,所以不管你依赖了多少个版本的 C,最终只会有一个版本的 C 被加载到 JVM 中。当 B 要去访问 Log.error,就会发现 Log 压根就没有 error 方法,然后就抛异常java.lang.NoSuchMethodError。这就是类冲突的一个典型案例。

类冲突的问题如果版本是向下兼容的其实很好解决,把低版本的排除掉就完事了。但要是遇到版本不向下兼容的那就陷入了“救妈妈还是救女朋友”的两难处境了。
为了避免两难选择,有人就提出了类隔离技术来解决类冲突的问题。类隔离的原理也很简单,就是让每个模块使用独立的类加载器来加载,这样不同模块之间的依赖就不会互相影响。如下图所示,不同的模块用不同的类加载器加载。
为什么这样做就能解决类冲突呢?这里用到了 Java 的一个机制:不同类加载器加载的类在 JVM 看来是两个不同的类,因为在 JVM 中一个类的唯一标识是 类加载器+类名。通过这种方式我们就能够同时加载 C 的两个不同版本的类,即使它类名是一样的。注意,这里类加载器指的是类加载器的实例,并不是一定要定义两个不同类加载器,例如图中的 PluginClassLoaderA 和 PluginClassLoaderB 可以是同一个类加载器的不同实例。

实现类隔离的原理是什么?
类隔离就是让不同模块的 jar 包用不同的类加载器加载,要做到这一点,就需要让 JVM 能够使用自定义的类加载器加载我们写的类以及其关联的类。
那么如何实现呢?一个很简单的做法就是 JVM 提供一个全局类加载器的设置接口,这样我们直接替换全局类加载器就行了,但是这样无法解决多个自定义类加载器同时存在的问题。
实际上 JVM 提供了一种非常简单有效的方式,我把它称为类加载传导规则:JVM 会选择当前类的类加载器来加载所有该类的引用的类。例如我们定义了 TestA 和 TestB 两个类,TestA 会引用 TestB,只要我们使用自定义的类加载器加载 TestA,那么在运行时,当 TestA 调用到 TestB 的时候,TestB 也会被 JVM 使用 TestA 的类加载器加载。
依此类推,只要是 TestA 及其引用类关联的所有 jar 包的类都会被自定义类加载器加载。通过这种方式,我们只要让模块的 main 方法类使用不同的类加载器加载,那么每个模块的都会使用 main 方法类的类加载器加载的,这样就能让多个模块分别使用不同类加载器。这也是 OSGi 和 SofaArk 能够实现类隔离的核心原理。
了解类隔离的实现原理之后,从重写类加载器开始进行实操。要实现类加载器,首先让自定义的类加载器继承 java.lang.ClassLoader,然后重写类加载的方法,这里有两个选择,一是重写 findClass(String name),二是重写 loadClass(String name)。
— 申请免费试学名额 —
在职想转行提升,担心学不会?根据个人情况规划学习路线,闯关式自适应学习模式保证学习效果
讲师一对一辅导,在线答疑解惑,指导就业!
相关推荐 更多
Java面试题之面向对象整理附答案
面向对象以数据为中心的开发方式,使用继承来简化开发过程,使用接口来规范对数据的操作,使用多态达到操作的灵活性。可以说面向对象是Java面试中的一个常见重要考点,因此本文为大家整理了面向对象的相关面试题,其中包括面向对象的特性、访问权限修饰符和clone对象的理解。大家可以结合着参考答案,梳理一遍面向对象的相关知识点。
9460
2019-12-04 14:01:29
Java面试之数据库知识点复习
数据库一直都是Java面试中的重点考察项目,本文为大家整理出来了常见的数据库知识点,内容主要有select语句完整的执行顺序、SQL之聚合函数、SQL之连接查询、SQL之sql注入、Mysql性能优化、MySQL 中文乱码问题完美解决方案。
6483
2020-05-04 14:24:56
MySQL数据库基础知识汇总梳理
本文对MySQL数据库基础知识进行了汇总和梳理,主要内容有认识数据库、常见数据库排行榜、SQL的概念以及DDL操作数据库。希望大家看完之后,能够能够理解数据库的概念,并且能够使用SQL语句操作数据库。
6912
2020-07-03 15:02:31
想学Java大学应该报哪个专业?
想学Java大学应该报哪个专业?大部分人会选择计算机应用技术或计算机科学与技术专业,里面涉及Java相关的课程,还有一些计算机基础知识,毕业以后从事软件开发的工作是比较对口的。Java是一种软件开发技术,大学一般不会重点教,会开这么一门课程,一周1-2个课时,教学内容相当有限算入门级别,想深入学习建议再报个Java培训班学习。
6712
2021-01-28 14:38:03
Java字节流输入输出数据的常用方法介绍
字节流由字节组成,在计算机中无论是文本、图片、音频还是视频所有文件都是以二进制(字节)形式存在,根据数据的传输方向可将其分为字节输入流和字节输出流。
4552
2021-04-23 13:53:46
