`
iamzhongyong
  • 浏览: 804594 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

类加载分析方案以及预防办法

    博客分类:
  • java
 
阅读更多

java类加载中的版本冲突是一个头疼的问题,这里列举几种排查问题以及处理的常用办法

 

有时候在测试环境下正常的,线上部分机器也是正常,但是有一些机器就会异常,这是啥原因?

因为jar包的加载顺序在不同的机器上面是不同的,一台机器多次重启,基本的顺序不会变,但是新的jar包就会有问题

 

 

在不同的机器上,对jar包中类的加载顺序有时候不是完全一致的,例如,在/home/admin/.default/lib 目录下的有个A.jar和b.jar,里面都有个叫SayHello的class,但A的SayHello里的功能(例如他打印的是“去你的”)和b的SayHello功能(例如他打印的是“你好”)不一样,

由于不同机器加载顺序可能不一致,那么就有可能A机器上先加载了A.jar的SayHello类(会打印出“去你的”),而B机器上加载了b.jar的SayHello类(会打印出“你好”)。

 

 

这个问题在特定的机器上,其加载顺序基本不变的,因此,一旦测试的时候没问题,那他就很难再重现出此问题,只有部署到线上多台机器上时,问题才可能会暴露出来。

 

 

 

(1)通过maven自带的几个工具来进行分析

 

 

1、mvn dependency:list能够列举出项目中的依赖情况

2、mvn dependency:tree打印出依赖出(\-代表行尾)  这个在排除依赖的时候非常有用,通过树状结构来查看jar包的加载情况

3、mvn dependency:analyzer 这个能够分析项目中的依赖情况。

 

Used undeclared dependencies 是指那些在项目中直接使用到的,但没有在POM中配置的依赖。要注意一点,这个分析是编译主代码和测试代码需要的依赖,运行时需要的没有打印出来。例如该例中可能项目中的一些类有关于spring-contextJava import声明,但spring-context这个依赖实际是通过传递性依赖进入classpath的,这就意味者潜在的风险。一般来说我们对直接依赖的版本变化会比较清楚,因为那是我们自己直接配置的,但对于传递性依赖的版本变化,就会比较模糊,当这种变化造成构建失败的时候,就很难找到原因。因此我们应当增加这些 Used undeclared dependencies

依赖分析还提供了 Unused declared dependencies 供我们参考,这表示那些我们配置了,但并未直接使用的依赖。需要注意的时,对于这些依赖,我们不该直接简单地删除。由于dependency:analyze只分析编译主代码和测试代码使用的依赖,一些执行测试和运行时的依赖它发现不了,因此还需要人工分析。通常情况,Unused declared dependencies 还是能帮助我们发现一些无用的依赖配置。

 

补充一个maven传递依赖的两个原则

 

maven的依赖调节机制有两个原则,一个是路径最近者优先,一个是第一声明者优先。
(1)最短路径优先
例如项目A中有这样的依赖关系,A->B->C->X(1.0) A->D->X(2.0) 分别传递依赖了X包的两个版本,
此时X(1.0)的路径为3,X(2.0)的路径为2,maven优先使用2.0)这个包
(2)第一声明者优先
上面这个原则不能解决所有问题,例如X(1.0)和X(2.0)的路径相同,这时候会使用那个包?
在依赖路径长度相同的情况下,POM依赖声明的顺序决定了谁会被解析使用,顺序靠前的那个依赖优先使用。
例如:
A->B->Y(1.0) A->C->Y(2.0)
如果B的依赖声明在C之前,则Y(1.0)版本会被解析使用。
 

 

(2)在应用启动的时候通过-verbose来进行分析

这个能够辅助进行一些分析,不过jvm启动参数上面加入-verbose可能会导致jboss挂起,可以使用,但是不要作为常态化来使用

 

 

1、在JVM的启动参数里面加入“-verbose”,这样会在日志里面显示类加载的信息;

2、输出JVM启动的时候的信息到特定的文件(可选)-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=<path>

 

 

通过脚本抓取日志里面从WEB-INF中加载的jar

grep '^\[Loaded.*/WEB-INF/lib.*' jboss_stdout.log | awk '{print $4 }' | cut -d'/' -f10 | cut -d']' -f1 |sort -u

 

 

(3)在编译阶段就预警出问题来,

在编译后,可以通过两种方式来进行

1、在WEB-INF目录下的lib中,解压jar包,然后递归比较类文件名称,如果有一个类名称相同的文件出现在两个jar包中,则有可能会发生冲突,提示出来即可

 

2、遍历maven插件,在编译的时候进行校验。

 

大体过程可以分为两步,第一步通过maven自带的API获取所有的jar包文件

第二步,遍历文件,将所有的类信息放到map或者set中,然后进行比较,如果文件曾经出现过,则提示有可能冲突。

 

    private MavenProject project;


    private boolean failOnWarning;

    @SuppressWarnings("unchecked")
    public void execute() throws MojoExecutionException, MojoFailureException {
        Set<Artifact> artifacts = project.getArtifacts();
        HashMap<String, Artifact> classAndArtifactMap = new HashMap<String, Artifact>();
        boolean hasWarnings = false;
        for (Artifact artifact : artifacts) {
            ZipInputStream zis = null;
            try {
                zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(artifact.getFile())));
                ZipEntry entry;
                while ((entry = zis.getNextEntry()) != null) {
                    if (entry.isDirectory() || !entry.getName().endsWith(".class")) {
                        continue;
                    }
                    if (classAndArtifactMap.containsKey(entry.getName())) {
                        hasWarnings = true;
                        getLog().warn("DUPLICATED CLASS FOUND! " + entry.getName() +
                                "\r\n\t" + artifact +
                                "\r\n\t" + classAndArtifactMap.get(entry.getName()));
                        break;
                    }
                    classAndArtifactMap.put(entry.getName(), artifact);
                }
            } catch (Exception e) {
                throw new MojoExecutionException("Unknown errors...", e);
            } finally {
                IOUtils.closeQuietly(zis);
            }
        }
        if (failOnWarning && hasWarnings) {
            throw new MojoFailureException("PLEASE CHECK ABOVE WARNINGS!!! There is duplicated classes found in your dependencies.");
        }
    }
 

 

 

 

第一种方式在排查问题的时候非常有用,第二种方式不推荐,极力推荐在编译阶段就把有可能存在类冲突的类查出来

 

分享到:
评论

相关推荐

    win7下vs2008”加载安装组件时遇到问题“解决办法

    下面将详细介绍可能的原因以及具体的解决方案。 #### 一、问题分析 1. **系统兼容性问题**:Windows 7发布于Visual Studio 2008之后,因此可能存在兼容性差异。 2. **Windows Installer服务异常**:Windows ...

    预制箱梁预压专项技术方案设计.doc

    4. **应急预案**:可能出现的问题和应对策略,如加载过程中发现异常变形或设备故障的处理办法。 5. **质量控制**:预压后的质量检查和验收标准,确保预压后的预制箱梁满足设计要求。 以上内容构成了一个完整的预制...

    Java内存溢出解决办法

    解决方法包括增大堆大小(通过-Xms和-Xmx设置),优化对象创建和销毁,减少内存泄漏,以及使用更高效的集合类,如使用`LinkedHashMap`替代`HashMap`来避免全表扫描。 2. **栈内存溢出(Stack OutOfMemoryError)**...

    visio2007崩溃解决办法

    ### visio2007崩溃解决办法 在日常的工作与学习过程中,我们常常会遇到软件崩溃的情况,这对于依赖这些工具完成任务的人来说无疑是个大问题。本文将针对Visio 2007在Windows 7系统上出现频繁崩溃的现象提供一些有效...

    基于实时视频分析的入侵监测系统设计与实现.zip

    【readme.md】: 这个文件通常包含项目的概述、安装步骤、数据集说明、模型训练和测试的指导,以及可能遇到的问题和解决办法。阅读此文件是理解项目结构和运行项目的首要步骤。 【test.py】: 这是一个Python脚本,很...

    删除eclipse3.4的configuration目录导致eclipse无法启动的解决办法

    ### 删除Eclipse 3.4的configuration目录导致Eclipse无法启动的解决办法 在使用Eclipse 3.4的过程中,有些用户可能会遇到这样的情况:为了安装新的插件或添加新的jar包,他们选择了删除Eclipse安装目录下的`...

    PB插入OLE控件崩溃的解决办法

    ### PB插入OLE控件崩溃的解决办法 #### 知识点概述 在使用PowerBuilder(简称PB)开发过程中,有时会遇到插入OLE控件时程序崩溃的问题。这不仅影响了开发效率,还可能导致项目的延期。本文将针对这一问题提供详细...

    精通CSS高级Web标准解决方案.pdf

    虽然标题和描述都指向了“精通CSS高级Web标准解决方案”,但实际内容并未提及CSS或Web标准相关的信息。因此,我们将基于现有内容中的技术细节来生成相关知识点。 ### 安装Office 2007及Microsoft Project过程中遇到...

    VS2010 deffactory.dat cannot be opened 解决方案

    总之,“VS2010 deffactory.dat cannot be opened”问题虽然令人头疼,但通过上述分析和解决方案,大部分情况下都能找到合理的解决办法。保持冷静,按部就班地排查,是解决此类技术问题的关键。

    蚂蚁课堂-JVM快速入门2

    解决方案可能涉及调整-XX:MaxMetaspaceSize参数,或者分析和减少类的使用。 学习这些内容对于Java开发者至关重要,因为它们不仅有助于解决实际开发中的问题,还能提升代码质量和系统性能。理解JVM参数设置,可以...

    交学院高大模板支撑安全专项方案

    1. **风险因素分析及对策**:评估潜在的安全风险,并制定相应预防措施。 2. **应急小组**:组建专门的应急小组,负责处理突发事件。 3. **事故报告流程**:明确事故发生后的报告程序。 4. **应急措施**:制定具体的...

    无法打开IE二级网页的处理办法

    ### 无法打开IE二级网页的处理办法 在日常使用Internet Explorer(以下简称IE)浏览器的过程中,可能会遇到一种较为特殊的情况——能够正常访问一个网站的主页,但在点击主页中的链接尝试访问二级网页时却无法成功...

    Java内存溢出问题

    解决方案可以是:限制应用的类加载数量,优化类的设计,避免大量动态生成的类;对于JDK8及以后版本,方法区已改为元空间(Metaspace),可以通过-XX:MaxMetaspaceSize来调整大小。 4. 本地方法栈溢出: 本地方法栈...

    扩展模块”不能使用解决办法

    在IT领域中,扩展模块是软件开发过程中一个重要的组成部分,它能够帮助开发者增强...通过上述详细的分析和指导,希望能够帮助用户有效地解决“扩展模块”无法使用的问题,并提供一些预防措施来避免未来出现类似的问题。

    电子表格打开表格出现book1文档的解决办法

    ### 电子表格打开表格出现book1文档的解决办法 在使用电子表格软件(如Microsoft Excel)的过程中,有时候用户会遇到一个普遍的问题:每次启动Excel时都会自动创建一个名为“Book1”的空白工作簿。虽然这看似只是一...

    FANUC机器人SYST-212报警PAUSE.G需要应用DCS参数的解决办法.docx

    - 定期维护和校准机器人是预防这类问题发生的有效手段之一,有助于保持机器人的最佳工作状态。 综上所述,对于FANUC机器人SYST-212报警PAUSE.G的问题,通过遵循正确的步骤进行操作,通常可以有效地解决。在处理过程...

    matlab开发-测量电桥模型参数的计算

    这两个参数对于理解桥梁的动态特性、评估其结构稳定性以及预防可能的安全隐患至关重要。 首先,我们要了解什么是悬索桥的本征频率。本征频率是物体自然振动的固有频率,不受外界激励的影响。在桥梁工程中,计算本征...

    广联达软件报错及解决办法.pdf

    通过上述分析与解决策略的介绍,我们可以看到针对广联达软件中常见的错误提示,用户可以根据自身情况采取适当的措施解决问题。当然,对于一些更深层次的技术问题,建议及时联系官方技术支持,以获得更加专业和精准的...

Global site tag (gtag.js) - Google Analytics