Jenkins共享库中使用Swagger Parser出现类型不兼容错误求助
我来帮你拆解这个问题——你碰到的java.lang.VerifyError: Bad type on operand stack本质是Jackson版本冲突,而且是Jenkins环境特有的类加载问题导致的:
Jenkins本身自带了一套Jackson库(通常是比较旧的版本,比如2.8.x系列),而你通过@Grab手动引入了2.9.1版本的Jackson相关包。在Jenkins的类加载机制下,这两套不同版本的Jackson类被加载到了不同的类加载器中,导致YAMLFactory虽然是JsonFactory的子类,但在类型校验时被当成了完全不兼容的类型,最终抛出了这个错误。
下面给你几个可行的解决方案,按推荐优先级排序:
1. 适配Jenkins自带的Jackson版本(最稳妥)
首先确认Jenkins当前自带的Jackson版本:
- 打开Jenkins的脚本控制台(Manage Jenkins > Script Console)
- 执行以下代码:
从输出的路径里可以看到Jenkins自带的Jackson版本(比如路径里的println com.fasterxml.jackson.core.JsonFactory.class.getProtectionDomain().getCodeSource().getLocation()jackson-core-2.8.11.jar就对应2.8.11版本)。
然后调整你的@Grab依赖,去掉手动引入的Jackson包,换一个和Jenkins自带Jackson版本兼容的Swagger Parser版本。比如如果Jenkins用的是2.8.x的Jackson,你可以试试swagger-parser:1.0.34(这个版本依赖的Jackson是2.8.x系列),修改后的Grab注解如下:
@Grab('io.swagger:swagger-parser:1.0.34') @Grab('org.apache.httpcomponents:httpclient:4.5.5') @Grab('org.yaml:snakeyaml:1.18')
2. 强制依赖加载到系统类加载器(快速临时方案)
如果一定要用2.0.0-rc1版本的Swagger Parser,可以通过@GrabConfig强制让Grapes把依赖加载到Jenkins的系统类加载器中,避免类加载隔离导致的类型冲突:
@GrabConfig(systemClassLoader=true) @Grab('io.swagger:swagger-parser:2.0.0-rc1') @Grab(group='com.fasterxml.jackson.core', module='jackson-databind', version='2.9.1') @Grab(group='com.fasterxml.jackson.dataformat', module='jackson-dataformat-yaml', version='2.9.1') @Grab('org.apache.httpcomponents:httpclient:4.5.5') @Grab('org.yaml:snakeyaml:1.18')
⚠️ 注意:这个方法可能会影响其他依赖Jackson的Jenkins插件,建议在测试环境充分验证后再用到生产环境。
3. 打包依赖到Jenkins核心(长期稳定方案)
如果你的团队经常需要在共享库中使用这个依赖,可以把Swagger Parser和兼容版本的Jackson、HttpClient等依赖打包成一个单独的jar,放到Jenkins安装目录的WEB-INF/lib下,然后重启Jenkins。这样所有共享库都可以直接使用这些类,完全避免动态引入的冲突问题。
内容的提问来源于stack exchange,提问作者TrafLaw

