基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
AIHT
内容
精选全部 AI 动态热点榜AI 日报收藏
分类
模型行业编程产品技术观点开源
更多
Agent 接入
返回首页开发者导航
AIHT
精选 / 资讯详情
8.0
热点
AI SCORE
编程提效2026-10-29 10:32

用本地模型解读Java旧代码并生成重构差异

dev.to · AI#遗留代码#本地模型#Java
Editor brief · 编辑速览

Exorcist结合Git历史和本地Ollama模型,在终端解释Java类、标注代码异味,并引用相关代码行。重构建议以统一差异格式输出,不直接修改文件,代码处理留在本机。

文章思维导图
Knowledge map
拖拽缩放
AI deep read

AI 深度解读

让老代码的作者「回来」解释设计、承认坏味道,再给出重构 diff,这是 Exorcist 的玩法。它从 Git 历史中找出 Java 类的主要贡献者,让本地模型扮演对方,在终端里讲代码。

但值得读的不是这个万圣节包装,而是作者如何约束一个会编故事的 7B 模型:先用 Git 和静态分析提供事实,再检查引用、替换范围和语法。实测也暴露了边界:行号可以全对,解释照样会错;文件能解析,重构照样可能无法编译。

让作者开口,靠的是 Git 证据

Exorcist 是一个基于 Java 21、Spring Boot、Spring Shell、Spring AI、JGit 和 JavaParser 的终端应用。默认模型为 qwen2.5-coder:7b,通过 Ollama 在本机运行。

工作流分三步:summon 扫描仓库,possess 选择一个类并解释,confess 列出代码问题;需要重构时再执行 exorcise。

作者拿 JUnit 4 做了演示:仓库从 2000 年 12 月起有 2,521 次提交,扫描历史不到五秒,找到 450 个 Java 类。随后选中的 junit.runner.BaseTestRunner 有 326 行、30 次提交和 10 个 catch 块。

这些数字描述的是作者的演示环境,原文没有提供硬件配置,也没有跨仓库性能对照。

「主要作者」的口径,是对该文件提交次数最多的人。扫描跳过 merge,追踪文件重命名;同一个人在多年间更换姓名和邮箱,则通过并查集归并身份。并查集可以理解成一套传递关系:两个身份分别与第三个身份对应,就能归到同一人。

JUnit 中的 dsaff <dsaff> 和 David Saff <saff@google.com>,正是通过 dsaff <david@saff.net> 连起来的。工具同时避开 noreply@github.com 这类共享占位邮箱,防止把陌生人合并。git blame 再补充哪些行最后由其他人修改。

这比直接让模型猜历史可靠,但「提交最多」仍不等于最了解设计的人。演示中,文件最后修改日期是 2016-10-15,模型扮演的作者却说自己最后修改于 2004-10-24。这可能是文件时间和个人贡献时间的区别,阅读时需要分清,不能把角色独白当成真实访谈。

行号和静态扫描,能把回答约束到哪一步

作者认为,角色口吻只需要一段系统提示词,真正困难的是阻止模型自信地乱说。

Exorcist 先给源码加行号,要求每条判断引用位置,再检查回答中的引用数量、行号是否越界,以及编号条目是否缺少引用。演示里的 [12 line citations, all inside the file] 是程序检查结果,干净时显示绿色,有问题时显示黄色。

第二层约束来自 JavaParser。模型开口前,静态扫描已经找出空 catch、宽泛 catch、printStackTrace()、System.out、深层嵌套、长方法、公开可变字段、Vector / Hashtable、@Deprecated 和 TODO,并附上准确行号。

模型的任务是结合证据解释问题,而非从零寻找一切。

在一次 confess 演示中,模型列出六项问题,包括长达 48 行的 getTest()、吞掉异常的 catch,以及直接使用 System.out.println()。作者称自己逐项核对,六项都真实存在,行号也正确。

其中一段代码足以说明为什么仍要看原文:

} catch (Exception IOException) {
    return stack; // return the stack unfiltered
}

要看清第一行:捕获的类型是 Exception,IOException 只是变量名。名字像某种异常,不代表实际捕获的就是它。作者说这段代码从 2000 年起就存在于 JUnit 中。

然而,作者另一次初始运行曾在两个条目里虚构 IOException,还重复报告同一个问题。当时引用的行号也是对的。

引用检查证明的是回答可以定位,不能证明回答符合那几行代码的含义。

静态命中也需要语境。宽泛 catch 可能隐藏错误,也可能处于刻意设计的兼容边界;检测到它,距离判定「应该怎么改」还有一步。

重构 diff 由程序生成,仍过不了编译这一关

exorcise 没有要求小模型直接输出 patch。作者发现,小模型容易生成损坏的补丁,于是把任务拆开。

工具先选择一个静态扫描确认的问题,再扩大到能够完整修改它的最小代码范围,例如整个 try 语句、单条语句或整个方法。随后要求模型输出 REPLACE LINES a-b 和代码块。

Exorcist 负责拼接替换内容、修正缩进、检查文件是否仍能解析,最后用 JGit 计算 diff。它不会把修改写入磁盘。

这里的分工很实用:模型负责建议代码,行范围、文本拼接和差异计算交给确定性程序。长文件还会裁成相关行附近的窗口,并明确告诉模型哪些内容不可见,以适应小模型的上下文容量。

问题在于,语法合法远远不够。

作者第一次 exorcise 就生成了无法编译的修改:它删掉失败分支后的 return null,还捕获了 try 内代码根本不会抛出的异常。Exorcist 当时只检查解析,作者计划下一步结合项目 classpath 编译替换后的文件。

换成 gemma3:4b 后,情况更差。它把三行方法说成臃肿,试图把整个方法塞进一个 13 行的替换范围;这次工具发现文件无法解析,拦住了结果。它还攻击真实维护者的编程能力,促使作者增加第五条提示规则:评价代码,不评价人。

项目有 98 个测试,不需要模型或网络。作者使用 Claude Code 结对开发,写测试时找出四个真实缺陷,其中一个会导致模型被要求重写自己根本没见过的行。

这些测试能检查工具自身的约束逻辑,却不能替每一次生成结果担保。

我的判断

我认可这里的工程顺序:先收集可验证事实,再让模型解释,最后检查输出。对旧系统维护而言,带位置的错误通常比无法追溯的漂亮解释更容易发现和纠正。

但「让作者说话」适合作为交互包装,不适合作为可信度来源。模型没有访问作者当年的想法,Git 也只能记录修改,不能完整记录决策动机。角色越逼真,读者越需要区分史料和推测。

与常规静态分析相比,Exorcist 增加了自然语言解释和修改建议;与直接把整个类交给聊天模型相比,它增加了事实输入与程序校验。原文没有给出准确率、误报率或维护耗时的对照数据,因此「更有效」目前还是经验判断。qwen2.5-coder:7b 与 gemma3:4b 的表现差异,也不足以单独证明参数规模决定可靠性。

本地运行的价值更明确:按原文描述,仓库和模型都在同一台机器上,模型下载完成后可离线使用,不需要 API key 或账户,也没有按次提问费用。不过仍有硬件、内存、电力和等待成本。原文没给出这些数据,也没给出生成速度。

至于「开放模型才方便比较」的说法,我会保留意见。同样的提示也可以用于比较不同托管 API;本地方案更直接的优势,是源码处理位置和运行环境由使用者控制。

能拿来做什么

  • 接手有完整 Git 历史的 Java 项目时,可以先用它梳理类的职责、贡献记录和异常处理位置,再回到引用行核对。前端或全栈开发者排查 Java 服务时,也能借此降低第一次阅读的门槛。
  • 在日常 AI 编程工具里,可以复用「带行号的输入、明确的可见范围、可检查的输出」这套做法。如果处理 Node 或前端代码,需要另配相应解析器和规则,原文没有证明 Exorcist 支持这些语言。
  • 把生成 diff 视为待审建议。用于实际重构前,除了语法检查,还应跑项目编译和相关测试,重点检查返回路径、异常类型与行为变化。
  • 如果代码需要留在本机,可以评估 Ollama 的本地路线。更换模型时,用 EXORCIST_MODEL=gemma3:4b 这样的配置在相同代码上比较,并记录错误类型,别只比较回答是否流畅。
Original source

本文由 AI 通读原文后重新编写,观点部分为站内判断,细节以原文为准,来源 dev.to · AI,原文版权归原作者所有。

阅读原文
上一篇
Claude 文档问答如何选长上下文与检索
下一篇
为iOS端侧转写增加模型回退,扩展语言覆盖

资讯速览

dev.to · AI · 2026-10-29 10:32

AI 评分 8.0 / 10

相关标签

#遗留代码#本地模型#Java

继续阅读

  • 内容审核实战:异步分流与人工兜底
  • Claude 文档问答如何选长上下文与检索
  • 为iOS端侧转写增加模型回退,扩展语言覆盖
  • 让Claude Code新增页面沿用项目设计
  • 国产模型API价格对比:区分涨价与代际溢价