山西网络建站代运营,百度seo营销公司,微信电商小程序有哪些,深圳市住房和建设局网站->认租申请前言JDK9引入了Java模块化系统(Java Platform Moudle System)来实现可配置的封装隔离机制#xff0c;同时JVM对类加载的架构也做出了调整#xff0c;也就是双亲委派模型的第四次破坏。前三次破坏分别是#xff1a;双亲委派模型推出之前#xff0c;SPI机制#xff0c;以及O…前言JDK9引入了Java模块化系统(Java Platform Moudle System)来实现可配置的封装隔离机制同时JVM对类加载的架构也做出了调整也就是双亲委派模型的第四次破坏。前三次破坏分别是双亲委派模型推出之前SPI机制以及OSGI为代表的热替换机制这里不细说。双亲委派模型简介在JDK9引入之前绝大多数Java程序会用下面三个类加载器进行加载启动类加载器(Bootstrap Class Loader)由C编写负责加载jrelib目录下的类例如最基本的ObjectInteger这些存在于rt.jar文件中的类一般这些类都是Java程序的基石。扩展类加载器(Extension Class Loader)负责加载jrelibext目录下的类在JDK9之前我们可以将通用性的类库放在ext目录来扩展JAVA的功能但实际的工程都是通过maven引入jar包依赖。并且在JDK9取消了这一类加载器取而代之的是平台类加载器(Platform Class Loader)下面会对其介绍。应用类加载器(Application Class Loader)负责加载ClassPath路径下的类通常工程师编写的大部分类都是由这个类加载器加载。工作顺序解释如果一个ClassLoader收到了类加载的请求他会先首先将请求委派给父类加载器完成只有父类加载器加载不了子加载器才会完成加载。源代码下面代码保留了核心逻辑并添加了注释主要是2个步骤如果父类加载器不为空则用父类加载器加载父类加载器加载不成功则本身再加载 Class c findLoadedClass(name); //如果该类没加载过 if (c null) { try { //如果有父类加载器 if (parent ! null) { //使用父类加载器加载 c parent.loadClass(name, false); ... } } if (c null) { ... //父类加载器没有加载成功则调用自身的findClass进行加载 c findClass(name);... } } 值得注意的是这里的parent并不是继承上的父子关系而是组合关系的父子parent只是类加载器的一个参数。图示如果觉得上面的解释比较抽象可以看看下面比较形象的图示这里的敌人就是我们要加载的jar包缺点通过上面的漫画不言而喻当真正的敌人来了靠这种低效的传达机制怎么可能打一场胜仗呢启动类加载器负责加载jrelib目录扩展类加载器负责加载jrelibext目录应用类加载器负责加载ClassPath目录。既然一切都是各司其职为什么不能加载类的时候一步到位呢通过分析JDK9的类加载器源码我发现最新的类加载器结构在一定程度上是缓解了这种情况的JDK的模块化在JDK9之前JVM的基础类以前都是在rt.jar这个包里这个包也是JRE运行的基石。这不仅是违反了单一职责原则同样程序在编译的时候会将很多无用的类也一并打包造成臃肿。在JDK9中整个JDK都基于模块化进行构建以前的rt.jar, tool.jar被拆分成数十个模块编译的时候只编译实际用到的模块同时各个类加载器各司其职只加载自己负责的模块。模块化加载源码 Class c findLoadedClass(cn); if (c null) { // 找到当前类属于哪个模块 LoadedModule loadedModule findLoadedModule(cn); if (loadedModule ! null) { //获取当前模块的类加载器 BuiltinClassLoader loader loadedModule.loader(); //进行类加载 c findClassInModuleOrNull(loadedModule, cn); } else { // 找不到模块信息才会进行双亲委派 if (parent ! null) { c parent.loadClassOrNull(cn); } }上面代码就是破坏双亲委派模型的“铁证”而当我们继续跟进findLoadedModule会发现是根据路径名找到对应的模块而维护这一数据结构的就是下面这个Map。Map packageToModule new ConcurrentHashMap(1024);可以看到LoadedModule里面不仅有该模块的loader信息还有用于描述依赖模块对外暴露模块的信息的mrefLoadedModule也是模块化实现封装隔离机制的一块重要实现。每一个module信息都有一个BuiltinClassloader这个类有三个子类我们通过源码分析他们的父子关系在ClassLoaders类中可以发现PlatformClassLoader的parent是BootClassLoader而AppClassLoader的parent则是PlatformClassLoader。public class ClassLoaders { // the built-in class loaders private static final BootClassLoader BOOT_LOADER; private static final PlatformClassLoader PLATFORM_LOADER; private static final AppClassLoader APP_LOADER; static { BOOT_LOADER new BootClassLoader((append ! null !append.isEmpty()) ? new URLClassPath(append, true) : null); PLATFORM_LOADER new PlatformClassLoader(BOOT_LOADER); ... APP_LOADER new AppClassLoader(PLATFORM_LOADER, ucp); } }结论经过破坏后的双亲委派模型更加高效减少了很多类加载器之间不必要的委派操作JDK9的模块化可以减少Java程序打包的体积同时拥有更好的隔离线与封装性每个moudle拥有专属的类加载器程序在并发性上也会更加出色