`
javapolo
  • 浏览: 130304 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

采用类加载器解决jar hell(jar冲突)问题

    博客分类:
  • jvm
 
阅读更多

问题描述:

由于历史原因,系统采用了很早期的poi,而最新的poi和之前版本并不兼容,现在要系统要增加一个新功能,需要引入最新的jar文件,在不影响已有使用的基础上,我们如何处理该问题?

解决方案:

本人的思路是写一个类加载器,动态的加载所需的jar文件到一个单独的命名空间,由于jvm默认的类加载是采用父委托机制的,但在这里,类加载器的实现思路和一些web 容器的类加载机制是一致的(如tomcat jetty等) ,即优先加载自己指定路径下的jar文件,如果加载不到所需的类文件则委托给父加载器,所以我们需重写ClassLoader的loadClass方法,最后上代码,代码很简单,但有一点比较重要,即默认java类所依赖的类是采用和该类相同的类加载器加载的

 

public class ParentLastClassLoader extends ClassLoader{
 
   private String[] jarFiles; //jar文件路径
   
   private Hashtable classes = new Hashtable(); //将定义的类缓存在hashtable里面
 
   public ParentLastClassLoader(ClassLoader parent, String[] paths)
   {
       super(parent);
       this.jarFiles = paths;
   }
 
   @Override
   public Class<?> findClass(String name) throws ClassNotFoundException
   {
       throw new ClassNotFoundException();
   }
 
   @Override
   protected synchronized Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException
   {
       try
       {
           byte classByte[];
           Class result = null;
           //先从缓存中查看是否已经加载该类
           result = (Class) classes.get(className);
           if (result != null) {
               return result;
           }
          //如果没找到该类,则直接从jar文件里面加载
           for(String jarFile: jarFiles){
               try {
                   JarFile jar = new JarFile(jarFile);
                   JarEntry entry = jar.getJarEntry(className.replace(".","/") + ".class");
                   InputStream is = jar.getInputStream(entry);
                   ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
                   int nextValue = is.read();
                   while (-1 != nextValue) {
                       byteStream.write(nextValue);
                       nextValue = is.read();
                   }
                   classByte = byteStream.toByteArray();
                   if(classes.get(className) == null){
                   result = defineClass(className, classByte, 0, classByte.length, null);
                   classes.put(className, result);
                   }
               } catch (Exception e) {
                   continue;
               }
           }
           result = (Class) classes.get(className);
           if (result != null) {
               return result;
           }
           else{
               throw new ClassNotFoundException("Not found "+ className);
           }
       }
       catch( ClassNotFoundException e ){
           return super.loadClass(className, resolve);
       }
   }
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics