最近在搞一个动态加载外部jar包,进行动态加载和调用的项目,外部包的类加载用继承于URLClassLoader类加载器的一个自定义类加载器,为的是打破原始的双亲委派机制。
项目内部类就用项目自己的默认类加载器,最开始用的是ClassLoader.getSystemClassLoader()即AppClassLoader。ok,然后再IDE用启用测试,一切正常,内部类用AppClassLoader加载,外部类用自定义类加载器加载都成功了。
结果发布到测试环境,测试时发现一堆java.lang.NoClassDefFoundError,分析ClassLoader源码良久,没有头绪,因为本地IDE各种加载都是好的,上了测试环境就各种类加载失败。
发现java -jar方式启动,此处打印的系统默认加载器是springboot的LaunchedURLClassLoader,而不是APPClassLoader
Java -Jar是以FAT JAR的方式用LaunchedURLClassLoader来load class。而在IDE中则是直接以ApplicationClassLoader来load的。这种差别会导致调用classloader.getResourceAsStream()得到不一样的结果,这是因为FAT JAR启动时,LaunchedURLClassLoader的load的urls并没有FAT JAR本身,如abc-0.0.1-SNAPSHOT.jar, 但是应用中的src/main/resources/META-INF/resources目录被打包到了FAT JAR里,也就是abc-0.0.1-SNAPSHOT.jar!/META-INF/resources,这样这些resource也就不会被访问到了
原文链接:https://blog.csdn.net/twj13162380953/article/details/124880414
标签:load,插件,springboot,jar,JAR,FAT,整包,resources,加载 From: https://www.cnblogs.com/silyvin/p/18392505