Page 17 - 《软件学报》2026年第7期
P. 17
2702 软件学报 2026 年第 37 卷第 7 期
图 5 展示了 JEP 126 中 Lambda 表达式的使用描述总结示例. 在该示例中, LumiX 对 Lambda 表达式相关内容
进行了结构化归纳, 具体包括该特性的名称、所属 JEP 编号、首次引入的 Java 版本, 以及对 JEP 核心内容的简洁
描述. 同时, LumiX 还为新特性的使用提供了一段代表性的代码示例, 用以展示 Lambda 表达式在实际编程中的典
型用法, 为后续自动化的代码生成与推荐任务提供了明确的语义和结构参考.
“id”: 5,
“featureName”: “Lambda Expressions & Virtual Extension Methods”,
“version”: 8,
“description”: “Introduces lambda expressions and default methods in interfaces.”,
“jepNumber”: “JEP 126”,
“exampleCode”: “names.forEach (name → System.out.println (“Hello,” + name));…”,
“sourceUrl”: “https://openjdk.org/jeps/126”,
“isPreview”: false,
“availability”: true,
图 5 新特性使用描述总结示例
在完成 JEP 中所有新特性使用描述的总结后, LumiX 便可以构建一个新特性使用描述池. 该描述池包含每个
特性的名称、引入版本、功能描述以及典型使用代码示例等关键信息, 为后续基于语言特性的代码生成任务提供
内容支持.
3.2 新特性测试程序生成
给定随机选择的新特性使用描述, LumiX 会以该描述作为生成依据, 结合大模型和程序分析工具构造一段能
够覆盖对应语言特性使用方式的代码片段, 并将其插入至种子程序中生成新的测试程序. 需要注意以下几点.
(1) LumiX 利用大模型所生成的并非完整的测试程序, 而是聚焦于语言新特性的代码片段. 其主要原因在于, 通过
控制生成内容的规模和复杂度, 使大语言模型能够更专注于特定语言特性的代码生成任务, 从而降低生成过程中
因引入上下文噪声或无关结构而导致的偏差. (2) 为了增强生成新特性测试程序的揭错能力, LumiX 使用历史揭错
测试程序作为种子程序, 为新生成的新特性代码片段提供丰富的上下文信息. 其主要原因在于, 历史揭错程序曾触
发测试目标的历史缺陷, 因此包含更具揭错能力的程序特征和路径. 为了提升代码片段与种子程序的交互, LumiX
利用程序分析工具解析当前种子程序中可复用的程序元素, 以此引导大模型在生成代码片段的过程中引入与种子
程序的语义交互. (3) 新生成的代码片段将被插入至种子程序中, 从而生成可以覆盖新特性的测试程序. 接下来, 本
节将分别介绍 LumiX 中可复用程序元素识别、新特性代码片段生成以及测试程序生成这 3 个任务.
3.2.1 可复用程序元素识别
历史揭错种子程序可以为新生成的代码片段提供丰富的上下文信息. 然而, 直接将新生成代码片段插入至种
子程序中, 通常难以构造具有语义交互与结构复杂性的测试程序. 孤立的代码片段通常缺乏与种子程序内容已有
代码的联系, 从而限制了测试程序的揭错能力. 但若将完整种子程序直接传给大模型, 让其选择插入点及构建丰富
的语义交互, 则会造成大模型幻觉的累积, 降低生成的效率及合法性 [38] . 为此, LumiX 利用程序分析工具分析当前
种子程序中可复用的程序元素, 如已定义的变量, 函数返回值等信息. 可复用元素的识别一方面为大模型的代码生
成提供了丰富的上下文信息, 另一方面通过变量修改与函数调用改变执行路径, 从而影响程序的控制流与数据流
依赖, 实现新特性片段与种子程序之间的有效交互.
具体来说, 给定种子程序 S, LumiX 首先会将 S 中所有的方法都解析为抽象语法树 (abstract syntax tree, AST).
随后, LumiX 随机选择种子程序中的一个方法以及该方法中的一个 AST 节点作为新生成代码片段的插入点. 需要
注意的是, LumiX 选择对 AST 进行解析而非控制流和数据流. 其主要原因在于, AST 是编程语言编译过程中的基
础组成部分, 避免了对更高级程序分析工具的依赖. 接下来, LumiX 将对该节点所有可复用的程序元素进行分析,
从而为新生成的代码片段提供上下文信息. 算法 1 展示了 LumiX 获取种子程序中可复用程序元素的算法, 该算法
以种子程序 S、被随机选中的插入点 I 以及插入点所在方法的抽象语法树 T 作为输入, 输出则是在插入点 I 处所
有可复用的程序元素集合 R. 在该算法中, LumiX 首先在 IdentifyReuseableElements 函数中识别可以复用的全局变
量以及函数定义 (第 3、4 行). 随后, LumiX 通过调用 TraverseAST 函数识别被选择方法中插入点 I 之前可以被复

