记一次java.lang.ClassNotFoundException问题排查过程

news/2024/4/20 2:59:11/文章来源:https://blog.csdn.net/wuxiaolongah/article/details/129248491

记一次java.lang.ClassNotFoundException问题排查过程

同事提供一个or-simulation-engine.jar包(非maven项目,内部依赖很多其他jar,这个包是手动打出来的)给我,我集成到我的springboot项目中,在本地IDEA启动Springboot后,相关功能都是正常的;但是将Springboot项目打成app.jar后,使用java -jar app.jar方式启动后,运行时爆出java.lang.ClassNotFoundException: com.anylogic.libraries.modules.markup_descriptors.DescriptorFactory

为什么IDEA可以执行,打成jar包使用java -jar就执行不了呢?
以下内容都是使用java -jar app.jar测试的结果。

一、代码定位

jar包依赖关系:我的app.jar依赖第二方or-simulation-engine.jar,而or-simulation-engine.jar依赖第三方com.anylogic.engine.jar

通过分析代码得知,or-simulation-engine.jar包在运行时,调用了如下代码:

String name = "com.anylogic.libraries.modules.markup_descriptors.DescriptorFactory";
ClassLoader systemCL = ClassLoader.getSystemClassLoader();
Class clazz = systemCL.loadClass(name);

这个代码是anylogic的jar包:com.anylogic.engine.jar中的内容。

具体异常信息:

java.lang.ClassNotFoundException: com.anylogic.libraries.modules.markup_descriptors.DescriptorFactoryat java.net.URLClassLoader.findClass(URLClassLoader.java:382)at java.lang.ClassLoader.loadClass(ClassLoader.java:424)at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)at java.lang.ClassLoader.loadClass(ClassLoader.java:357)at com.yonghui.or.simulation.controller.CoreController.test(CoreController.java:99)at com.yonghui.or.simulation.controller.CoreController$$FastClassBySpringCGLIB$$6a496143.invoke(<generated>)at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:749)

通过异常信息可以看出:ClassLoader.getSystemClassLoader()获得的是AppClassLoader,但是AppClassLoader并没有在对应的路径下加载到该类。但是该类确实是存在的,而且通过new或者Class.forname()都是可以找到该类的。

可以看到,or-simulation-engine.jar手动打完包后,内部依赖的jar都被放到了一起,不是以jar包的方式存在的。

image-20230227184433662

这可能是非maven项目or-simulation-engine手动打包有问题,导致集成到springboot项目打成app.jar后找不到该类了。

二、确定使用的ClassLoader

那么异常中的这个类com.anylogic.libraries.modules.markup_descriptors.DescriptorFactory应该使用哪个classloader加载呢?

可以使用jvm调优工具arthas,找到app.jar进程后,输入 sc -d com.anylogic.libraries.modules.markup_descriptors.DescriptorFactory命令,查看该类使用的类加载的情况:

image-20230227175936112

可以看到这里使用的是LaunchedURLClassLoader。而该加载器的上级才是AppClassLoader。

最终运行的java -jar app.jar的jar包是通过spring-boot-maven-plugin这个插件生成的, JAR中依赖的各个jar文件其实并不在运行时应用的classpath下(实际在app.jar/BOOT-INF/lib下存放所有依赖的jar包),也就是根据类加载的双亲委派机制,这些依赖没办法被默认的任何一个classloader加载,Springboot为了解决这个问题,自定义了类加载机制,LaunchedURLClassLoader就是Springboot自定义的类加载器。关于Springboot的类加载器可以查看:

        <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-loader</artifactId><scope>Provided</scope></dependency>

查看app.jar/META-INFO/MANIFEST.MF的内容,可以看到使用了spring-boot-loader包中的org.springframework.boot.loader.JarLauncher。这个类最后创建的就是LaunchedURLClassLoader。

image-20230227190532563

三、问题确认

通过上面的分析,可以确认问题的原因: app.jar依赖第二方or-simulation-engine.jar,而or-simulation-engine.jar依赖第三方com.anylogic.engine.jar。第三方的jar包为了代码安全,给代码做了相关的混淆等操作后,在代码运行时,使用动态ClassLoader.getSystemClassLoader()类加载器(AppClassLoader)动态加载自己的一个类;当所有的代码集成到springboot项目并用springboot-maven插件打包后,ClassLoader.getSystemClassLoader()就找不到对应的类了。
IDEA中启动不会有问题,是因为IDEA默认使用的是ApplicationClassLoader进行类加载的,而且classpath对应了多个jar包,包括jre/lib 、jre/lib/ext、本地mvn仓库、和app.jar项目路径。而java -jar方式的classpath只有app.jar。

四、解决方法

找到问题后,就可以针对性解决问题了。有两种方式:

1.改变打包方式,让打包后的代码内被ClassLoader.getSystemClassLoader()这个AppClassLoader找到;

2.修改第三方com.anylogic.engine.jar,将类加载器改成LaunchedURLClassLoader。

这两种方式的目的都是class文件放到所使用的类加载器对应的路径下。

方式一

将打包方式改成:

	<build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-jar-plugin</artifactId><version>2.6</version><configuration><archive><manifest><addClasspath>true</addClasspath><classpathPrefix>lib/</classpathPrefix><mainClass>com.example.helloloader.HelloLoaderApplication</mainClass></manifest></archive></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-dependency-plugin</artifactId><version>2.10</version><executions><execution><id>copy</id><phase>package</phase><goals><goal>copy-dependencies</goal></goals><configuration><outputDirectory>${project.build.directory}/lib</outputDirectory></configuration></execution></executions></plugin></plugins></build>

方式二

修改第三方com.anylogic.engine.jar,将类加载器改成LaunchedURLClassLoader。其实就是修改一行代码:

将:

ClassLoader systemCL = ClassLoader.getSystemClassLoader();

修改成:

 ClassLoader systemCL = Thread.currentThread().getContextClassLoader();

这样app.jar在运行时就可以获得LaunchedURLClassLoader。

这种方式需要反编译,如果将第三方com.anylogic.engine.jar整体反编译,部分class会编译失败,修改代码后也很难再编译成功。

这里有个简单的方式:新建一个空maven项目,在pom中引入本地的com.anylogic.engine.jar。然后按照要修改的class文件在第三方jar包内的包名,在该空项目中建相同的包和类名(com.anylogic.engine.markup.descriptors.IDescriptorFactory),并将反编译后的内容放入这个类中,再修改掉对应的一行代码。通过mvn clean packge重新打包,在target目录下找到这个IDescriptorFactory.class文件。

image-20230227193716288

然后用这个IDescriptorFactory.class替换掉第三方com.anylogic.engine.jar所对应的IDescriptorFactory.class.

如何替换?

首先解压:

 jar -xvf com.anylogic.engine.jar

然后找到并替换掉IDescriptorFactory.class

最后成jar包

 jar cvfM  com.anylogic.engine.jar ./

将新的jar包集成到项目中后就可以启动了。

参考:

https://docs.spring.io/spring-boot/docs/current/reference/html/executable-jar.html#appendix.executable-jar.restrictions

https://blog.csdn.net/wuxiaolongah/article/details/129245218

https://blog.csdn.net/kingwinstar/article/details/125482503

https://www.jianshu.com/p/1ec1189f2397

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_74899.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Telnet 基础实验1: Telnet 实验

Telnet 基础实验1&#xff1a; Telnet 实验 拓扑图 配置命令 R1 的配置 undo ter mo sys sys R1 interface g0/0/0 ip address 192.168.1.1 255.255.255.0 qR2 的配置 undo ter mo system-view sysname R2 interface g0/0/0 ip address 192.168.1.2 255.255.255.0 q两台设…

day21_IO

今日内容 上课同步视频:CuteN饕餮的个人空间_哔哩哔哩_bilibili 同步笔记沐沐霸的博客_CSDN博客-Java2301 零、 复习昨日 一、作业 二、File 三、IO流 四、字节输入&输出流 零、 复习昨日 见晨考 一、作业 见答案二、File 2.1 介绍 File,通过一个路径代表文件或者文件夹 …

mysql(一) 使用注意事项及优化

初学mysql的时候、写了一份 "什么是CRUD&#xff1f; CRUD的操作" 的文章&#xff08;18年的&#xff09; 我开心看到有朋友经常在下面讨论一些问题、 但是以现在&#xff08;今天 23年&#xff09;回头看觉得 那些只是入门需要知道和掌握的、也刚好最近不是很忙 所…

区块链行业遭供应链攻击,上万加密钱包被“抄底”损失上亿美元

当地时间8月2日晚间&#xff0c; 区块链行业遭遇了一次行业重创 。据科技媒体TechCrunch报道&#xff0c; 若干名攻击者“抄底”了上万个加密钱包&#xff0c;钱包内有价值上亿美元的代币。 据了解遭受攻击的加密钱包包括Phantom、Slope和TrustWallet等。涉及到的币种除了SOL、…

网上招聘系统

技术&#xff1a;Java、JSP等摘要&#xff1a;当今&#xff0c;人类社会已经进入信息全球化和全球信息化、网络化的高速发展阶段。丰富的网络信息已经成为人们工作、生活、学习中不可缺少的一部分。人们正在逐步适应和习惯于网上贸易、网上购物、网上支付、网上服务和网上娱乐等…

为什么文档对 SaaS 公司至关重要?

在过去十年左右的时间里&#xff0c;SaaS的兴起使全球数百家公司成为家喻户晓的公司。但他们并不是仅仅依靠产品的力量到达那里的。客户服务和支持是使一切在幕后顺利进行的原因——其中很大一部分是文档。以正确的风格和正确的位置在您的网站上找到适当的用户文档对于将浏览器…

RNN相关知识总结

目录RNN结构与原理1.模型总览2.反向传播LSTM结构与原理1.模型总览2.如何解决RNN梯度消失/爆炸问题&#xff1f;GRU结构及原理1.模型总览LSTM与GRU的区别RNN结构与原理 1.模型总览 上图是RNN的展开结构图&#xff0c;由输入层、隐藏层和输出层组成。当前时间步t 的隐藏状态hth_…

【神经网络】Transformer基础问答

1.Transforme与LSTM的区别 transformer和LSTM最大的区别就是LSTM的训练是迭代的&#xff0c;无法并行训练&#xff0c;LSTM单元计算完T时刻信息后&#xff0c;才会处理T1时刻的信息&#xff0c;T 1时刻的计算依赖 T-时刻的隐层计算结果。而transformer的训练是并行了&#xff0…

快速找到外贸客户的9种方法(建议收藏)

所有外贸企业想要做好外贸出口的头等大事&#xff0c;就是要快速的找到优质的外贸客户和订单&#xff0c;没有订单的达成&#xff0c;所有的努力都是图劳&#xff0c;还有可能会陷入一种虚假的繁荣&#xff0c;每天都很忙&#xff0c;但是没有结果。今天&#xff0c;小编就来分…

第一章 1:函数

函数概念 函数我们可以简单的理解为一个自变量只对应一个函数值&#xff0c;如图&#xff1a; 如图所示的图像&#xff0c;我们可以把其理解为函数&#xff0c;那非函数呢&#xff1f; 这个就叫做非函数&#xff0c;因为我们的一个自变量对应了两个函数值。 函数的两要素&…

极智项目 | 实战pytorch arcface人脸识别

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多经验分享 大家好&#xff0c;我是极智视界&#xff0c;本文介绍 实战pytorch arcface人脸识别&#xff0c;并提供完整项目源码。 本文介绍的实战arcface人脸识别项目&#xff0c;提供完整的可以一键训练、测试的项目工程…

不怕被AirTag跟踪?苹果Find My技术越来越普及

苹果的 AirTag 自推出以来&#xff0c;如何有效遏制用户用其进行非法跟踪&#xff0c;是摆在苹果面前的一大难题。一家为执法部门制造无线扫描设备的公司近日通过 KickStarter 平台&#xff0c;众筹了一款消费级产品&#xff0c;可帮助用户检测周围是否存在追踪的 AirTag 等设备…

【2023全网最全教程】从0到1开发自动化测试框架(建议收藏)

一、序言 随着项目版本的快速迭代、APP测试有以下几个特点&#xff1a; 首先&#xff0c;功能点多且细&#xff0c;测试工作量大&#xff0c;容易遗漏&#xff1b;其次&#xff0c;代码模块常改动&#xff0c;回归测试很频繁&#xff0c;测试重复低效&#xff1b;最后&#x…

小米无线AR眼镜探索版细节汇总

在MWC 2023期间&#xff0c;小米正式发布了一款无线AR眼镜&#xff0c;虽然还没看过实机&#xff0c;但XDA提前上手体验&#xff0c;我们从中进行总结。首先我要说的是&#xff0c;小米这款眼镜和高通无线AR眼镜参考设计高度重叠&#xff0c;产品卖点几乎一致&#xff0c;只是增…

微服务框架-学习笔记

1 微服务架构介绍 1.1 系统架构演变历史 单体架构垂直应用架构&#xff1a;按照业务线垂直划分分布式架构&#xff1a;抽出业务无关的公共模块SOA架构&#xff1a;面向服务微服务架构&#xff1a;彻底的服务化1.2 微服务架构概览 1.3 微服务架构核心要素 服务治理&#xff1…

观测云产品更新|新增用户访问监测自动化追踪;新增 CDN 质量分析;新增自定义查看器导航菜单等

观测云更新 用户访问监测优化 新增用户访问监测自动化追踪 用户访问监测新增自动化追踪&#xff0c;通过“浏览器插件”的实现方式&#xff0c;使用浏览器记录用户访问行为&#xff0c;创建无代码的端到端测试。更多详情可参考文档【 自动化追踪 】https://docs.guance.com/…

SpringBoot整合XxlJob

SpringBoot整合XxlJob 1.XxlJob简介 官方网址&#xff1a;https://www.xuxueli.com/xxl-job XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 为什么要使…

Macbook M1 安装PDI(Kettle) 9.3

Macbook M1 安装PDI(Kettle) 9.3 当前 PDI&#xff08;Kettle&#xff09;最新版为9.3&#xff0c;依赖Java JDK 11。因为没有专门用于 M1的程序&#xff0c;需要下载并安装x86_64架构的JDK及依赖软件&#xff0c;并 “强制在Intel模式下运行shell” 的方式来实现 Kettle 的正…

【YOLO系列】YOLOv4论文超详细解读1(翻译 +学习笔记)

前言 经过上一期的开篇介绍&#xff0c;我们知道YOLO之父Redmon在twitter正式宣布退出cv界&#xff0c;大家都以为YOLO系列就此终结的时候&#xff0c;天空一声巨响&#xff0c;YOLOv4闪亮登场&#xff01;v4作者是AlexeyAB大神&#xff0c;虽然换人了&#xff0c;但论文中给出…

【Project】项目管理软件学习笔记

一、前言使用Project制定项目计划步骤大致如下&#xff1a;以Project2013为例&#xff0c;按照上图步骤指定项目计划。二、实施2.1 创建空白项目点击文件——新建——空白项目&#xff0c;即完成了空白项目的创建&#xff0c;在此我把该项目保存为60mm项目管理.mpp&#xff0c;…