自定义ClassLoader,jar包无法加载jar包配置文件问题

 

会写自定义ClassLoader同学,相信你也对ClassLoader有一定的认识。或者你也可以帮我解惑一下..... 

URLClassLoader主要应用于加载外部jar包用的,通常我们通过URLClassLoader加载额外的jar包以解决依赖冲突问题。

但是测试的时候报出了一个异常:

Illegal Hadoop Version: Unknown (expected A.B.* format)

  Jar内用到hadoop组件,但是hadoop读取不到classpath下面的common-version-info.properties配置文件。

大概读了下hadoop的此处源码:

protected VersionInfo(String component) {
    info = new Properties();
    String versionInfoFile = component + "-version-info.properties";
    InputStream is = null;
    try {
      is = Thread.currentThread().getContextClassLoader()
        .getResourceAsStream(versionInfoFile);
      if (is == null) {
        throw new IOException("Resource not found");
      }
      info.load(is);
    } catch (IOException ex) {
      LogFactory.getLog(getClass()).warn("Could not read '" +
          versionInfoFile + "', " + ex.toString(), ex);
    } finally {
      IOUtils.closeStream(is);
    }
  }

发现源码用的:

Thread.currentThread().getContextClassLoader() .getResourceAsStream(versionInfoFile);

 读取的配置。

于是我在自定义ClassLoader里,将当前的ClassLoader放到了线程的ClassLoader里,代码如下:

ClassLoader classLoader = new URLClassLoader(new URL[]{new URL(url)}, Thread.currentThread().getContextClassLoader());
Thread.currentThread().setContextClassLoader(classLoader);

重新测试,测试通过~

===========================================================================

有几个问题:

1.Thread.currentThread().getContextClassLoader() .getResourceAsStream方式为什么加载不到jar包内的配置,而我在调用方的线程加了ClassLoader之后,这种方式就能加载到了?

说实话,我想的不是很明白,大家都知道双亲委派,自定义URLClassLoader A,去加载jar包,那么jar包内class的父类类加载器,应该为A ,但是我测试不把A放到当前线程的类加载器里的话,jar包内的类加载器为AppClassLoader且加载不到配置,如果把A放到当前线程的类加载器里,jar包内的类加载器为URLClassLoader且能加载到配置~~

我又测试了一下,如果不用Thread.currentThread().getContextClassLoader() .getResourceAsStream方式去加载配置,而是用Classxx.class.getClassLoader().getResourceAsStream去加载配置,不把自定义URLClassLoader A放到当前线程的类加载器里的,jar包内的类加载器为AppClassLoader且能加载配置!!!把A放到当前线程的类加载器里,jar包内的类加载器为URLClassLoader且也能加载到配置!!!

一个线程用自定义URLClassLoader去加载一个jar包里的类,jar包的类加载的父类到底是不是自定义URLClassLoader呢?通过上面的测试发现,如果用了线程内用了Thread.currentThread().setContextClassLoader(classLoader);那么jar包内用的ClassLoader一定是URLClassLoader。否则用的是AppClassLoader。

哪位兄台可以解决我的疑惑呢 TT

 

你可能感兴趣的:(java基础)