springboot分离打包,类加载器不一致导致依赖包中Class.forName反射报错classNotFound

文章来源原创   作者:临窗旋墨   发布时间:2022-04-27   阅读:2339   标签:spring,springboot 分类:我的linux 专题:解决方案

springboot分离打包,类加载器不一致导致依赖包中Class.forName反射报错classNotFound

重点: LaunchedURLClassLoader;了解类加载器的基本常识

问题描述:

  1. 项目为springboot项目,资源和主包分离打包。大体如下:

    1. -- application.jar 应用jar
    2. -- resources 资源文件
    3. -- lib:第三方jar
  2. 报错class not found:

    1. 应用中调用第三方jar包中的工具方法,工具方法中调用Class.forName(className)
    2. 这个className为主包中的对象

问题排查

小伙伴跟我反馈的问题是,在本地开发中都是好的,但是发布到测试环境就包这样的错了。

首先从以下几个方便简单确认了下:

  1. 对应的not found的class确实已经打包到测试环境
  2. 测试环境为快照版,但是并没有在jar中加入时间戳,即jar肯定也是存在且正确的。

​ 这个class类所在的包为主包,猜测应该是不在一个classLoader中

断点简单跟了一下,发现Class.forName中获取到classloader为“AppClassLoader”,

而主应用的class被加载到的是类加载器为LaunchedURLClassLoader, 两者不在一个classPaths.。 所以找不到该类。

修改方案:

Class.forName(className)修改为

Thread.currentThread().getContextClassLoader().loadClass(className)

其他说明

关于springboot,现在小伙伴们使用的比较多。 可能偶尔会出现一下开发环境没有问题,但是打包部署后就出出现一些问题的情况,特别是资源分离打包的情况下。

个人建议,这种情况下首先应该看看主jar包里的“MANIFEST.MF” 文件, 它包含了该包的所有情况,网上资料很多,此处不再赘述。

另外,关于springboot的类加载器LaunchedURLClassLoader,网上资料也很多,我随手就搜到一个Java classLoader spring LaunchedURLClassLoader, 有兴趣可以看看。

—— by 临窗旋墨

20220427


发表评论

目录