【问题标题】:Random build failures on JenkinsJenkins 上的随机构建失败
【发布时间】:2014-04-16 17:08:40
【问题描述】:

所以这个问题会有些模糊,我很抱歉,但我什至不知道从哪里开始。我们使用 Jenkins 在夜间自动化一些构建。我们使用 Maven 执行构建。有一段时间,一切都很顺利。我们有发现错误、代码覆盖率结果和成功构建的稳定历史。突然之间,在运行单元测试时,我们得到了随机的 NoClassDefFound 异常。这很奇怪,因为在此之前,日志消息清楚地表明它构建了源并成功了。然后单元测试开始运行,它们立即死亡,出现上述异常。我们最近确实对 Jenkins 进行了更新,但我并不完全相信这与它有很大关系。真正奇怪的部分是构建并不总是因为这个异常而失败。有时他们跑得很好,有时他们会立即失败。就失败的特定单元测试或无法找到的特定类而言,失败是不一致的。虽然它们似乎围绕着相同的一小部分类和单元测试,但似乎没有任何真正的模式。

有没有其他人在詹金斯上看到过 maven 构建?我真的不知道该怎么办。日志消息并不完全有用,我不知道我可以对 Jenkins 配置做些什么来从失败的构建中获得更好的调试信息。如果有人有任何想法,我可以收集任何人可能需要的任何信息。以下是最近失败的构建之一的示例堆栈跟踪:

com.ipti.ptl.common.problems.detectors.CMDRProblemDetectorTest.afterPropertiesSetTest

Failing for the past 3 builds (Since Unstable#411 )
Took 18 ms.
Error Message

com/ipti/hardware/bcicinterface/CPacketReceivedArgs
Stacktrace

java.lang.NoClassDefFoundError: com/ipti/hardware/bcicinterface/CPacketReceivedArgs
    at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2521)
    at java.lang.Class.getDeclaredMethods(Class.java:1845)
    at com.ipti.common.eventbus.EventBus.subscribe(EventBus.java:107)
    at com.ipti.ptl.common.problems.detectors.CMDRProblemDetector.afterPropertiesSet(CMDRProblemDetector.java:23)
    at com.ipti.ptl.common.problems.detectors.CMDRProblemDetectorTest.afterPropertiesSetTest(CMDRProblemDetectorTest.java:37

【问题讨论】:

  • @Chris No. 它只有默认构造函数、单个实例字段和实例方法。一个实例字段是我们的类之一,它也没有。

标签: java unit-testing maven jenkins noclassdeffounderror


【解决方案1】:

我也经历过类似的事情。随着时间的推移,我们学到了两个保持一致性的重要技巧:

  1. 每次构建时将构建配置为“检查新源”。有时事情可能会变得陈旧
  2. 检查您使用的是clean package 还是clean installinstall 会将工件存储在运行 Jenkins 的用户本地的 .m2 存储库中。如果您不是,任何给定的项目可能必须在构建期间从您配置的存储库中下载它的依赖项。我建议使用 clean install 只是为了让本地工件准备好进行依赖构建。

根据这两条规则仔细检查每个 Jenkins 构建是很重要的。相互依赖的项目之间的不一致也是随机混乱的根源。

【讨论】:

    【解决方案2】:

    除了@jmkgreen 所说的,或者如果您尝试了这些步骤但它们没有解决问题,我会检查工件的类路径中是否存在问题。 Surefire 和 JUnit 不保证测试将以特定顺序运行。以不同的顺序运行测试可能会导致以不同的顺序加载类并导致这些奇怪的问题。 This blog post 有一个非常好的解释。

    如果这似乎正在发生,您可以采取以下步骤来清理工件的依赖项。

    删除所有不需要的依赖项

    确保每个依赖项只包含一个版本(例如,只有一个 Spring 框架)。

    特别注意组 ID 或工件 ID 已更改的工件。对于这些情况,Maven 依赖关系解析过程无法检测到一个工件应该覆盖另一个工件并包含两者。这可能会导致有趣且有时不确定的问题。一个例子是spring.jarspring-core.jar

    如果应用程序包含多个支持相同功能的依赖项,您需要手动排除不需要的依赖项,如Maven documentation 中所述。

    确保相关依赖都使用同一个版本

    例如,如果项目包含多个 Spring 工件(spring-core、spring-jdbc、spring-aop 等),请确保它们的版本相同。使用dependencyManagement 或根据需要添加直接依赖项以使版本一致。

    将任何-all-type 依赖项替换为其组件部分

    ...并且只有项目需要的那些。 -all jars 可能包含运行库所需的每个类 - 重新打包到 jar 文件中,Maven 的依赖项解析过程无法获取它们 - 而不是将它们作为依赖项引用。

    例如,mockito-all contains a repackaged version of Hamcrest,它可以将conflict 与项目想要使用的任何其他版本的 Hamcrest 一起使用(并且在运行之前可能不会导致难以修复的问题!)。

    【讨论】:

      猜你喜欢
      • 2016-07-11
      • 2017-04-10
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 2018-07-25
      • 1970-01-01
      • 1970-01-01
      • 2015-02-24
      相关资源
      最近更新 更多