在进行非WEB项目(Springboot)进行开发时,使用classLoader进行动态加载jar,并使用接口进行强类型转换是没有问题的,它们使用JVM下的URLClassLoader进行实现,而在基于tomcat的容器里使用它时,出现了类型无法找到的问题,原因如下:
tomcat有个叫webApp的加载器它是先加载WEB-INF/classes后在加载WEB-INF/lib,但它的父加载器是它的common加载器,comon的父加载器是system加载器(和JVM的应用程序加载器功能差不多,不过指定了其他tomcat目录下的加载,大家可以看看官网上的英文文档),但是源码中这个加载器是URLClassLoader的子类,而URLClassLoader默认父加载tomcat下是它的system加载器这么设计和tomcat的
配置有关,默认为无为false,会直接委托给tomcat的system加载器加载system委托最顶层的Bootstrap加载器(差不多是JVM里起始加载器和扩展加载器的合并),但不管怎么样,项目在tomcat下自定义的或者URLClassLoader加载默认父加载器都不会是tomcat的webApp加载器而是system加载器,或者自定义的加载器或URLClassLoader和tomcat的webApp加载器没有上下关系,所以动态创建类时设计到其他类时肯定会报CNF异常。
参考
https://blog.csdn.net/chenleixing/article/details/50042795
https://blog.csdn.net/chenleixing/article/details/47121661
Tomcat ClassLoader
解决方法
一 解决思路就是先获取当前类的Class,然后获取当前类的加载器,在自定义的加载器或者URLClassLoader加载器创建时指定为它们的父加载器,这样问题就会游刃而解了,可能平常我们测试写个简单的例子没遇到这个问题,因为我们那时的URLClassLoader或者自定义的加载器的父加载器都是JVM的第三次加载器即应用程序加载,它是专门加载classpath下边的或者指定的类或者jar的,依照双亲委托模型,肯定会找到引入路径的那个类或者jar的。
二 使用Class.forName()的方式来动态加载指定的类,就不会存在这个问题,因为这种方式一方面是能初始化类的静态东西,再就是重要一点,就是采用的加载当前所在类的加载器来加载你指定的类,这样你在tomcat下那就是它的webApp加载器啊,肯定不再出现这个问题,可能直接就从缓存里找到了。
动态加载代码
URL url = new URL(packageUrl); // IDEA调试时与java运行时的ClassLoader是不同的,所以需要使用当前环境下的ClassLoader ClassLoader loader = new URLClassLoader(new URL[]{url}, clazz.getClassLoader()) { @Override public Class<?> loadClass(String name) throws ClassNotFoundException { try { String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class"; InputStream is = getClass().getResourceAsStream(fileName); if (is == null) { return super.loadClass(name); } byte[] b = new byte[is.available()]; is.read(b); return defineClass(name, b, 0, b.length); } catch (IOException e) { e.printStackTrace(); throw new ClassNotFoundException(name); } } };
原文转载:http://www.shaoqun.com/a/493209.html
拍拍:https://www.ikjzd.com/w/2205
扬帆计划:https://www.ikjzd.com/w/1581
欧舒丹:https://www.ikjzd.com/w/1756
在进行非WEB项目(Springboot)进行开发时,使用classLoader进行动态加载jar,并使用接口进行强类型转换是没有问题的,它们使用JVM下的URLClassLoader进行实现,而在基于tomcat的容器里使用它时,出现了类型无法找到的问题,原因如下:tomcat有个叫webApp的加载器它是先加载WEB-INF/classes后在加载WEB-INF/lib,但它的父加载器是它的c
网络星期一:网络星期一
母婴团购网:母婴团购网
速卖通直通车的使用方法简析!:速卖通直通车的使用方法简析!
2020年YouTube十大创意广告新鲜出炉!:2020年YouTube十大创意广告新鲜出炉!
深圳今年冬天会更冷吗?:深圳今年冬天会更冷吗?
No comments:
Post a Comment