Jenkins - 共享库和类加载

Jenkins - 共享库和类加载

我们正在为我们的 Jenkins 代码使用共享库 Jenkins 插件,即 Workflow-cps-global-lib。

我们在一个共享库中使用 Groovy 代码成功地在不同项目类型上实现了工作流。

今天我们遇到了一个似乎与类加载相关的问题,但我不知道问题出在哪里。

在我们的共享库中使用“JAXBContext”实例会导致 classcastexception。稍后我将更新确切的异常。

该类从我们詹金斯上安装的一些其他插件加载。

在某些时候,它是从 deployit-plugin(jenkins/plugins/deployit-plugin/web-inf/lib/jaxb-impl-xxx.jar)加载的。

安装 xlrelease-plugin(xlrelease-plugin/web-inf/lib/jaxb-impl-xxx.jar)后,似乎 JAXBContext 现在已从该插件加载,并且我们不再收到“ClassCastException”。

共享库插件与这些插件之间没有直接依赖关系。但我们的代码调用这些插件公开的方法。我现在的猜测是,由于我们在代码中调用这些插件,因此我们继承了它们的类路径。

如果是这样,那么我们如何控制调用哪个 jar 版本?我们尝试使用 grape 来获取我们的 jaxb 实现和 api 版本,但加载的 jaxbcontext 仍然是来自 xlrelease-plugin 的 jaxbcontext。

我查看了一下 github 上的 Workflow-cps-global-lib 代码。正如预期的那样,有一些类加载器操作。

但我没有找到指向其他插件的类加载器的关系的任何指针。

如果我正确理解了 Jenkins 文档中的内容,那么当插件 A 依赖于插件 B 时,插件类加载器会从插件 B 继承 jar。

https://jenkins.io/doc/developer/plugin-development/dependencies-and-class-loading/

“workflow-cps-global-lib” 不依赖于 xlrelease-plugin 或 deployit-plugin,因此不应继承它们的类路径。

如果有人知道为什么我在管道执行中加载这些类,那将会非常有帮助。

答案1

您找到了一个有效的文档,尽管它没有涉及从用户 Groovy 库代码加载类,而只涉及从插件中的代码加载类。Groovy 库从 提供类UberClassLoader,因此如果多个插件提供相同的类,则无法定义从哪里加载它。

(Jenkins 的最新版本包含一个真正的 JAXB 插件,它可能优先于那些。)

您可能能够通过明确@Grab绑定库所需的 JAR 来解决这个问题。但最好完全避免使用库中的 JAXB。进程内脚本和第三方库确实不能很好地混合使用。尝试坚持使用 Java 平台和 Groovy 内置程序来获得简单的“粘合”代码,对于任何实际计算,只需使用sh您选择的工具(理想情况下将部分或全部功能从 Groovy 库中完全移出)。

相关内容