最近做一个web项目,服务器用的是tomcat,需要一个动态添加jar库的功能(系统不停机),我在程序中用URLClassLoader动态加载新的jar,发现无法引用项目里面WEB-INF/lib下的jar库,老是报ClassNotFoundException,我在没有动态加载jar之前看了看原有jar中类的加载器是org.apache.catalina.loader.WebappClassLoader:
Class<?>c = Class.forName("org.slf4j.Logger");//slf4j的jar包在WEB-INF/lib目录下
out.print(c.getClassLoader().getClass().getName());
输出结果是WebappClassLoader,这个类是java.net.URLClassLoader的子类,属于最低优先级的类加载器,现在我用URLClassLoader加载新的jar文件,就出错:
String className;//类名
URL[] url;//url数组
//省略变量初始化,保证变量值正确
ClassLoader loader = new URLClassLoader(url);
Class<?> c = loader.loadClass(className);//这里抛ClassNotFoundException异常
Object obj = c.newInstance();
不过这里抛出的异常不是className没找到,而是className的父接口没找到,className父接口所在的jar包在WEB-INF/lib目录下。我尝试了下面两个办法解决:
1.用Java Instrumentation把className父接口所在的jar包加入系统classpath中,这时loadClass正常了,但是后面无法直接调用类的方法了,必须全部用反射调用,这样需要修改大量代码,就没有继续。
2.把WEB-INF/lib里面的jar全部拷到%JRE_HOME%\lib\ext里面,现在一切都正常了,但是这样需要修改系统配置,而我更希望能在程序代码中解决这个问题,或者最多是修改项目配置。
不知道大家还有没有其它解决方法,我希望能通过在ClassLoader下手解决。谢谢!