You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jenkins脚本式Pipeline读取txt文件循环报NotSerializableException异常

问题成因

抛出java.io.NotSerializableException: java.util.ArrayList$Itr异常的核心原因如下:

  • Jenkins脚本式Pipeline基于CPS引擎执行,运行过程中会定期将流水线上下文序列化生成持久化快照,用于故障恢复、跨节点调度等场景,所有留存于Pipeline上下文的对象必须实现Serializable接口,否则就会触发序列化异常。
  • 原有实现存在两处逻辑错误:
    • readFile步骤读取文件返回的是带换行符的完整字符串,并非按行拆分的列表结构;且env全局变量仅支持存储字符串类型,无法直接保存结构化列表对象,直接将读取到的字符串存入env.Mydata本身就不符合变量使用规则。
    • 直接对未做格式转换的变量调用each方法遍历时,Groovy隐式生成的ArrayList内部迭代器ArrayList$Itr属于私有内部类,未实现序列化接口,被CPS引擎纳入上下文快照捕获范围时,就会直接抛出异常。
修复方案

按以下逻辑调整代码即可,提供两种可稳定运行的实现方式:

  1. 注解封装方式(推荐,兼容所有Groovy原生语法)
    用@NonCPS注解修饰数据处理逻辑,被该注解标记的方法不会被CPS引擎做序列化拦截,内部可以正常使用Groovy原生的迭代语法:
    // 读取文件后按换行拆分,去除每行首尾空白、过滤空行,生成可序列化的ArrayList
    def mydata = readFile(file: 'values.txt').split('\n').collect { it.trim() }.findAll { !it.isEmpty() }
    
    // 标注@NonCPS,跳过该方法的CPS序列化检查
    @NonCPS
    def processItemList(List itemList) {
        itemList.each { currentVal ->
            // 此处填写原有遍历业务逻辑
            echo "当前处理值:${currentVal}"
        }
    }
    
    // 调用方法执行遍历
    processItemList(mydata)
    
  2. CPS兼容循环方式(无需额外注解)
    不使用each闭包迭代语法,改用基于索引的for循环实现遍历,不会生成非序列化的迭代器对象,天然适配CPS引擎的序列化要求:
    def mydata = readFile(file: 'values.txt').split('\n').collect { it.trim() }.findAll { !it.isEmpty() }
    // 基于索引的for循环,无额外非序列化对象生成
    for (int i = 0; i < mydata.size(); i++) {
        def currentVal = mydata[i]
        // 此处填写原有遍历业务逻辑
        echo "当前处理值:${currentVal}"
    }
    

注意事项:代码中所有引号、括号必须使用英文半角符号,不要使用中文全角符号,否则会触发语法解析错误;不要将列表、Map这类结构化对象存入env变量,跨阶段传递结构化数据直接使用def定义的局部变量即可。

内容的提问来源于stack exchange,提问作者user15824359

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:57:22