• JVM类加载器应用之多版本库支持


    问题

      开发过程中,咱们经常需要使用不同的库版本,而这些版本又不是向后兼容的,或者出于某种原因需要支持同一库的多个版本。

      在这种情况下,默认的类加载器已经是不支持了,因为 loadClass 方法只加载一次特定的类,之后所有的加载请求就直接返回现有 Class 实例的引用了。

    解决办法

      在这种情况下,可以自定义一个类加载器,用这个具有优先设置的加载器加载需要的库就可以了。

    基本代码如下:

     1 import java.net.URL;
     2 import java.net.URLClassLoader;
     3 import java.util.List;
     4 
     5 public class CustomClassLoader extends ClassLoader {
     6     private ChildClassLoader childClassLoader;
     7 
     8     public CustomClassLoader(List<URL> classpath) {
     9 
    10         super(Thread.currentThread().getContextClassLoader());
    11         URL[] urls = classpath.toArray(new URL[classpath.size()]);
    12         childClassLoader = new ChildClassLoader(urls, new DetectClass(this.getParent()));
    13     }
    14 
    15     @Override
    16     protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    17         try {
    18             return childClassLoader.findClass(name);
    19         } catch(ClassNotFoundException e) {
    20             return super.loadClass(name, resolve);
    21         }
    22     }
    23 
    24     private static class ChildClassLoader extends URLClassLoader {
    25         private DetectClass realParent;
    26 
    27         public ChildClassLoader(URL[] urls, DetectClass realParent) {
    28             super(urls, null);
    29             this.realParent = realParent;
    30         }
    31 
    32         @Override
    33         public Class<?> findClass(String name) throws ClassNotFoundException {
    34             try {
    35                 Class<?> loaded = super.findLoadedClass(name);
    36                 if(loaded != null) return loaded;
    37                 return super.findClass(name);
    38             } catch(ClassNotFoundException e) {
    39                 return realParent.loadClass(name);
    40             }
    41         }
    42     }
    43 
    44     private static class DetectClass extends ClassLoader {
    45         public DetectClass(ClassLoader parent) {
    46             super(parent);
    47         }
    48 
    49         @Override
    50         public Class<?> findClass(String name) throws ClassNotFoundException {
    51             return super.findClass(name);
    52         }
    53     }
    54 }

    All Done!

      至此就算完成了,通过这种解决办法就可以使单个 jvm 中有多个库版本,或者同一个版本中由于静态变量导致的多实例共存了。

    注意:有些库中可能还加载了一些 classpath 下的资源文件,这种情况下就按需要覆盖 getResource 等方法就可以了。

  • 相关阅读:
    报名用户主题看板
    有效线索主题看板 阿善有用 清洗转换具体怎么做
    意向客户主题看板 阿善看到 阿善用到 拉链表
    数据库建模 全量表导入
    git 阿善有用
    IDEA+git+码云
    Cloudera Manager的基本使用 阿善没用
    cloudera manager报错解决方案
    java-多态简述及实例
    java-简述接口及实例
  • 原文地址:https://www.cnblogs.com/liboware/p/12495961.html
Copyright © 2020-2023  润新知