java自定义classloader在加载jar包和classes的时候,classloader不能找到classpath下的配置文件
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java自定义classloader在加载jar包和classes的时候,classloader不能找到classpath下的配置文件相关的知识,希望对你有一定的参考价值。
最近在写一个应用程序中间件,发现自定义的classloader加载app的jar包和classes时,发现加载不到app自己classpath下的配置文件,必须放到中间件的classpath下才能找到,我想知道是不是java的每个自定义classloader都要设置一个classpath啊,可是也没找到这个方法啊,不知道哪去设置每个app自己的classpath;tomcat的webclassloader也没看明白怎么去实现的,就是希望中间件能隔离每个app的jar和classes,为每一个app创建一个classloader,可是就是app里自己的jar或者classes找不到它需要的配置文件啊,我们都知道,在编写app时候都是在eclipse里设置classpath去找,可是自定义classloarde后,classpath就变成了中间件自己的classloader,迷糊了,死啃tomcat7源代码都脑袋疼了
设我们有一个hello.jar文件,里面有一个Util类,我们希望在运行期调将这个jar包放入到我们运行环境并且调用里面的Util.getVersion方法。怎么实现?在java中,我们的类都是通过ClassLoader来加载的,同时ClassLoader具有层级关系,当某个类找不到时,它会去他的父类加载器去寻找,如果依然找不到,就抛出ClassNotFoundException了。
为了动态加载hello.jar里面的Util类,我们需要将这个jar包放入到我们的类加载器中去,然后再获取里面的类。如下面的代码。
// 位于hello.jar
package com.flyingzl;
public class Util
public static void getVersion()
System.out.println("java version: " + System.getProperty("java.version"));
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class Main
public static void main(String[] args)
URL[] urls = new URL[] ;
MyClassLoader classLoader = new MyClassLoader(urls, null);
try
classLoader.addJar(new File("c:/hello.jar").toURI().toURL());
Class<?> clazz = classLoader.loadClass("com.flyingzl.Util");
Method method = clazz.getDeclaredMethod("getVersion");
method.invoke(null);
classLoader.close();
catch (Exception e)
e.printStackTrace();
static class MyClassLoader extends URLClassLoader
public MyClassLoader(URL[] urls)
super(urls);
public MyClassLoader(URL[] urls, ClassLoader parent)
super(urls, parent);
public void addJar(URL url)
this.addURL(url);
注意:这里仅仅是为了展示如何动态加载jar包,代码写得很粗,生产代码需要有更完善的异常处理。我们只关心如何动态加载jar包即可。
动态加载jar包,需要用到java.net.URLClassLoader这个类,它可以指定一个路径将jar包或者classes文件加载到类空间。加载完毕后,直接调用loadClass就可以加载指定的类,然后通过反射生成实例或者调用方法即可。
其实,Tomcat等服务器也利用了此思路,比如每一个web应用启动时,它都会自动加载其下的lib文件夹下的jar包。
运行程序,我们就可以看到程序正常输出:
java version: 1.7.0_03追问
哎,写了一堆,居然没了,太坑了,这样简单说吧,getVersion方法有段代码:Util.class.getResource("/config/version.xml"),Main创建的Classloader去加载Util类,
invoker getVersion时会找不到version.xml,尽管打包的时候和jar包放一起的路径
以上是关于java自定义classloader在加载jar包和classes的时候,classloader不能找到classpath下的配置文件的主要内容,如果未能解决你的问题,请参考以下文章
java自定义classloader在加载jar包和classes的时候,classloader不能找到classpath下的配置文件
web工程中添加自建userLibary与将jar包放到lib文件夹下的区别
classloader加载class的流程及自定义ClassLoader