NoClassDefFoundError/ClassNotFoundException 到底从哪引用到了这个类?排查思路

2023-11-14


1、背景

公司内网登录改造升级,使用方需要配合升级 jar 包。

本以为很简单的事情,升级版本上线就 OK 了。没想到升级头一个服务,部署到测试环境就有问题。

2、表象

访问所有页面报 404。

3、排查思路

3.1 排除法,确定是不是升级 jar 包的问题

版本回退后,一切正常,所以可以肯定是新版本 jar 包的问题。

3.2 服务启动是否正常

升到新版本继续排查,看了服务进程在,启动日志也正常,查看 tomcat 日志发现报错了。

java.lang.NoClassDefFoundError: com/xxx/.../MarCouponDto
        at java.lang.Class.getDeclaredMethods0(Native Method) ~[?:1.8.0_92]
        at java.lang.Class.privateGetDeclaredMethods(Class.java:2701) ~[?:1.8.0_92]
        at java.lang.Class.getDeclaredMethods(Class.java:1975) ~[?:1.8.0_92]
        at org.springframework.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:606) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:518) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.util.ReflectionUtils.doWithMethods(ReflectionUtils.java:504) ~[spring-core-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.determineCandidateConstructors(AutowiredAnnotationBeanPostProcessor.java:241) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors(AbstractAutowireCapableBeanFactory.java:1069) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1042) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:510) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834) ~[spring-context-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537) ~[spring-context-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:446) ~[spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:328) [spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107) [spring-web-4.2.0.RELEASE.jar:4.2.0.RELEASE]
        at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4939) [catalina.jar:7.0.42]
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5434) [catalina.jar:7.0.42]
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150) [catalina.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1559) [catalina.jar:7.0.42]
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1549) [catalina.jar:7.0.42]
        at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_92]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [?:1.8.0_92]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [?:1.8.0_92]
        at java.lang.Thread.run(Thread.java:745) [?:1.8.0_92]
Caused by: java.lang.ClassNotFoundException: com.xxx.MarCouponDto
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1714) ~[catalina.jar:7.0.42]
        at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1559) ~[catalina.jar:7.0.42]
        ... 30 more

3.3 检查新版本 jar 包中的 pom 依赖

看名字,需要找的 MarCouponDto 和升级的 jar 包、和这个服务没有半毛钱关系。
先从 pom 文件中看看有没有相关的依赖。从 pom 中看了相关的依赖,层级很深,没有办法直接找到相关的依赖。
使用 DependencyAnalyzer 搜索相关的依赖,也没搜到。

3.4 录屏 + 断点调试,根据堆栈信息定位问题点

单从堆栈信息也看不出哪里用到了这个类,但可以肯定的是在 Spring 初始化 bean 的时候用到了。
但 Spring 启动要初始化那么多 bean,一个一个的断点要到猴年马月。
这个时候就想到了录屏,调试的时候打开录屏,快速结束。然后再回放视频,看看最后在哪里结束的。

cd1c12df71cc15b16822536e128a04fa.png

通过录屏找到初始化出错的类后,就可以采用条件断点一次定位了。

d12de13ebb7b5d1bb18ff794b094cb92.png

竟然把业务的实现也打到包里了,无语 。。。

3a6701f733a56e549e6d130469fefd33.png

重新定位到断点后,根据堆栈信息往回找到 beanDefinition,因为 beanDefinition 中包含了 class 的 source 信息,可以直接找到这个 class 是在哪个包中被加载的。

96ab9b10571d4340e7c8d54907d540d1.png

3.5 再从 pom 中查看依赖关系

知道了从哪个包依赖后,再次从 DependencyAnalyzer 搜索包名,就能够得到依赖树了。

b68583016d3b4d39e8a3e926a72c4979.png

排除依赖后,再次启动,此错误消失。

扯两句

jar 包中不要依赖无关的内容,尤其还有业务实现,害人又害己。

如果大家都遵守基本的开发规范,就不会把大量时间浪费在处理这类问题上了。

原创不易,多多关注,一键三连,感谢支持!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

NoClassDefFoundError/ClassNotFoundException 到底从哪引用到了这个类?排查思路 的相关文章

随机推荐

  • hortonworks/registry配置详解

    1 美图 2 配置 deploy demo db registry cat conf registry yaml registries configuration modules name schema registry className
  • 什么是CSRF攻击,以及如何防御

    什么是CSRF攻击 以及如何防御 1 CSRF攻击的概念 2 CSRF攻击简单案例 2 1 银行网站项目 2 2 危险网站的项目 2 3 测试 3 默认的CSRF防御策略 4前后端分离的CSRF防御策略 1 CSRF攻击的概念 1 CSRF
  • MPI群通信与矩阵乘法的Fox算法实现

    原本以为 MPI天生只能在Linux上运行 但这次却发现了Intel MPI Library 这个好用的东西 基本不需要设置 安上之后 用自己能登录windows的帐号和密码注册就行了 虽然不是局域网上的机器 但也可以让我的双核CPU达到1
  • WebSocket协议之NGINX代理转发无法建立连接问题处理

    WebScoket协议如需要通过nginx代理 需要location 节点增加以下节点即可正常建立连接 需要配置以下节点 proxy http version 1 1 proxy set header Upgrade http upgrad
  • Python入门网络爬虫之精华版,赶快收藏

    相关文件 关注小编 私信小编领取哟 当然别忘了一件三连哟 公众号 Python日志 前言 Python学习网络爬虫主要分3个大的版块 抓取 分析 存储 另外 比较常用的爬虫框架Scrapy 这里最后也详细介绍一下 举例子 当我们在浏览器中输
  • STL 中集合操作相关算法

    merge 头文件 merge 算法定义在头文件 include 中 算法作用 merge 算法是合并两个有序的序列 合并结果拷贝到一个新的序列 前提是这两个序列的排序规则一样 代码示例 vector
  • vue---UI框架elementUI实现系统登录注册页

    https blog csdn net maidu xbd article details 87943243已经搭建好了vue开发环境 在本博客中 来介绍些结合element ui实现登录注册界面 界面效果展示如下图 实现的功能包括 首先安
  • 【数据结构】红黑树模拟实现

    一 红黑树底层原理 红黑树的底层可以看作是AVL树的变种 先前我们了解过AVL的模拟实现 avl对整棵树的控制还是非常严格的 因为高度差不能大于2 导致会经常发生旋转 旋转这个过程也会降低效率 所以为了整体的效率衍生出了红黑树 红黑树旋转的
  • 稳压二极管工作原理、重要参数意义和典型电路参数计算

    稳压二极管的工作原理 稳压二极管也叫稳压管 它在电路中一般起到稳定电压的作用 也可以为电路提供基准电压值 稳压二极管使用特殊工艺制造 这种工艺使它在反向击穿时仍然可以长时间稳定工作 不损坏 而工作在反向击穿状态的稳压管只要工作电流保持在一定
  • 电感磁芯公式

    NBA LI
  • [机缘参悟-89]:《本质思考》- 本质思考的7种习惯

    目录 一 精准性思考 精确 表面词语要精确 二 非歧义思考 深度 明确表面词语背后的动机 三 多维度思考 广度 全方面思考 四 反馈式思考 确认 反复确认 五 适应性思考 变化 因环境变化而变化 六 循环式思考 持续改进 逐渐得到问题的本质
  • linux more 下一页_Linux more命令如何使用?

    Linux下的more命令主要用于分屏显示 即内容超过一屏的文件 与cat命令有点区别 下面小编就给大家详细介绍下more命令 有兴趣的话不妨来了解下吧 more会以一页一页的显示方便使用者逐页阅读 而最基本的指令就是按空白键 space
  • git:分支合并

    1 git 分支的合并 merge 假设我们此时需要修复dev分支上的某个bug 此时在dev分支上创建修复分支fix 然后推进fix分支 当前的git仓库如图 注 为了方便演示 dev分支上只有一个test cpp源文件 然后我们在fix
  • 利用Visio绘制数据流图

    http blog sina com cn s blog a3059cda01011meg html 利用Visio 2007来绘制网上书店系统的数据流图 利用Visio 2007创建Gane Sarson数据流图 可以选择 软件和数据库
  • 【满分】【华为OD机试真题2023 JS】简单的自动曝光

    华为OD机试真题 2023年度机试题库全覆盖 刷题指南点这里 简单的自动曝光 时间限制 1s 空间限制 256MB 限定语言 不限 题目描述 一个图像有n个像素点 存储在一个长度为n的数组img里 每个像素点的取值范围 0 255 的正整数
  • 使用OpenCV库实现的模板轮廓匹配定位功能块

    c include
  • 批处理替换修改文件名

    echo off echo echo title 批量替换文件名中的部分字符串 color 3f echo Note echo 本批处理可批量替换本文件所在文件夹下的所有文件名的相同字符 echo echo echo echo echo e
  • CentOS 8 通过二进制安装 MySQL

    需求 CentOS8下采用二进制安装包的形式安装MySQL 并且指定数据库文件存放的路径地址 步骤如下 在 MySQL下载地址 中下载 MySQL 二进制安装包 注意 在版本选择的时候 版本号在8 0 11及以下包后缀都是 tar gz 但
  • Python中from from __future__ import *的用法

    from future import 参考 https blog csdn net zzc15806 article details 81133045 我们在读代码的时候 总是会看到代码开头会加上from future import 这样的
  • NoClassDefFoundError/ClassNotFoundException 到底从哪引用到了这个类?排查思路

    1 背景 公司内网登录改造升级 使用方需要配合升级 jar 包 本以为很简单的事情 升级版本上线就 OK 了 没想到升级头一个服务 部署到测试环境就有问题 2 表象 访问所有页面报 404 3 排查思路 3 1 排除法 确定是不是升级 ja