问题背景
同一个JVM进程中,往往会部署不同的java应用,不同业务开发人员会采用同一个组件包的不同版本,此时部署在同一个JVM中会出现常见的JAR冲突问题,导致涉及的多个应用无法正常使用。那么,怎样才能实现不同应用正常使用各自版本的组件包呢?那就是类加载隔离。
实现原理
类加载机制,众所周知是双亲委派机制,意思是加载一个类,优先从当前类加载器的父加载器加载,找不到再从当前加载器加载。依赖关系如下:
因此,各个应用使用的公共jar可以通过Extension Classloader或Application ClassLoader加载,不同版本的同路径class应该自定义类加载器去加载,就避免了向上委托只能找个某一个版本的class的问题。自定义的类加载器的依赖结构如下:
自定义类加载器,主要是用来管理私有的class或jar,比如只加载指定目录下的class或者jar。根据如下图的class装载的流程,我们知道,重载类加载器中findClass方法是行之有效的(当然也可以扩展具体的ClassLoader,比如URLClassLoader,它已经将findClass逻辑写好,就不需要重写。只需要addURL(jar url)即可),loadClass不变可以保证不打破双亲委派机制。
业界方案
作为一个启动应用程序的容器,需要管理内部加载的所有jar,对应用程序的可见性范围,否则会造成类加载混乱,造成应用无法正常使用。比如常见的Tomcat、SOFAArk等类隔离机制。