Java 类结构提取工具 —— 一键生成 GitHub 项目的 UML 类图 JSON
dataset-builder 是一个 Java 类结构提取工具,能够分析托管在 GitHub 上的 Java 项目,并生成结构化的 JSON UML 类图。它会克隆目标仓库,以 AST 级别精度解析每个 .java 文件,输出包含类节点(字段与方法,含可见性和类型)以及类间关系(继承、实现、关联、依赖)的图模型。
手动为大型 Java 代码库编写类架构文档既繁琐又容易出错。本工具将其自动化——输入一个 GitHub 地址和模块路径,即可生成整个类图的结构化 JSON。输出可被图表库(如 GoJS)直接消费、导入机器学习训练数据集,或用于代码审查与架构分析。
系统分为两层——Python 编排层和 Java 分析引擎——通过子进程边界通信。
用户 CLI (--repo, --module)
│
▼
┌─────────────────────────────┐
│ Python 控制器 │
│ │
│ main.py (argparse) │
│ git_cloner.py (git clone) │
│ java_invoker.py (subprocess)│
└──────────┬──────────────────┘
│ java -jar parser.jar <源码路径> <输出路径>
▼
┌─────────────────────────────┐
│ Java 解析引擎 │
│ │
│ Main.java (入口) │
│ ProjectAnalyzer (扫描) │
│ UmlVisitor (AST) │
│ model/ (DTO) │
│ FileUtil (I/O) │
└──────────┬──────────────────┘
│ GraphLinksModel JSON
▼
output/*.json
- 输入:GitHub 仓库地址 + 相对模块路径(如
gson/src/main/java) - 克隆:Python
git_cloner.py将仓库克隆到repos/目录 - 调用:Python
java_invoker.py启动java -jar指向已克隆的源码 - 分析:Java
ProjectAnalyzer递归查找.java文件,使用 JavaParser 的 AST 引擎逐一解析,并通过UmlVisitor访问类声明 - 解析:SymbolSolver 跨文件解析类型引用,以准确检测类间关系
- 输出:Gson 将
GraphLinksModel(节点 + 连线)序列化为格式化 JSON
| 模块 | 语言 | 职责 |
|---|---|---|
python-controller/python/main.py |
Python | CLI 入口,编排 克隆→分析 流水线 |
python-controller/python/git_cloner.py |
Python | 克隆/更新 GitHub 仓库 |
python-controller/python/java_invoker.py |
Python | 调用 Java JAR 并验证 JSON 输出 |
java-parser/.../Main.java |
Java | JAR 入口;串联 解析→分析→序列化 |
java-parser/.../core/ProjectAnalyzer.java |
Java | 文件扫描、AST 解析、节点与关系构建 |
java-parser/.../core/UmlVisitor.java |
Java | AST 访问器,提取类成员与元数据 |
java-parser/.../model/ |
Java | 数据模型:GraphLinksModel、NodeData、LinkData、Property、Method、Parameter |
java-parser/.../utils/FileUtil.java |
Java | 递归查找 .java 文件及 UTF-8 文件写入 |
| 层级 | 技术 | 版本 | 用途 |
|---|---|---|---|
| 编排层 | Python 3 | — | CLI、Git 操作、子进程管理 |
| 核心引擎 | Java | 17 | AST 解析、类型解析 |
| Java 解析器 | com.github.javaparser:javaparser-core |
3.25.5 | Java 源码 AST 解析 |
| 符号解析 | com.github.javaparser:javaparser-symbol-solver-core |
3.25.5 | 跨文件类型解析 |
| JSON 序列化 | com.google.code.gson:gson |
2.10.1 | Java 对象 → JSON |
| 构建工具 | Maven + maven-shade-plugin |
3.4.1 | 含依赖的可执行 Fat JAR |
| 版本控制 | Git | — | 仓库克隆 |
- 一条命令完成提取 — 指向任意公开的 GitHub Java 仓库,一次 CLI 调用即可获得完整类图
- AST 级精度 — 使用 JavaParser(而非正则表达式)解析源码,正确处理泛型、注解和嵌套类型
- 丰富的类元数据 — 提取类名、包名、构造型(
Class)、字段(名称、类型、可见性)和方法(名称、返回类型、参数、可见性) - 四类 UML 关系检测:
- 继承(
extends) - 实现(
implements) - 关联(字段类型引用项目内其他类)
- 依赖(方法参数与返回类型引用项目内其他类)
- 继承(
- 符号解析 — 使用 JavaParser 的 SymbolSolver 跨文件解析类型,确保基于
import的引用被正确链接 - GoJS 兼容输出 — JSON 架构(
GraphLinksModel,含nodeDataArray和linkDataArray)可被 GoJS 图表库直接消费 - 增量克隆支持 —
--no-clone标志允许在已克隆的仓库上重复运行分析
- Java 17+,
java命令需在PATH中 - Maven(用于构建 Java JAR)
- Python 3.8+ 及
pip - Git(用于克隆仓库)
# 1. 克隆项目
git clone https://github.com/jkllvfree/dataset-builder.git
cd dataset-builder
# 2. 安装 Python 依赖
cd python-controller
pip install -r requirements.txt
# 3. 构建 Java 解析器(Fat JAR)
cd ../java-parser
mvn clean package构建完成后,可执行 JAR 位于:
java-parser/target/java-parser-0.0.1-SNAPSHOT.jar
cd python-controller/python
# 基本用法:从 GitHub 仓库提取类结构
python main.py --repo <github-url> --module <java源码相对路径>
# 示例:分析 Google Gson 的主源码树
python main.py --repo https://github.com/google/gson --module gson/src/main/java| 参数 | 必填 | 默认值 | 说明 |
|---|---|---|---|
--repo |
是 | — | GitHub 仓库地址 |
--module |
否 | (仓库根目录) | 克隆后仓库内 Java 源码的相对路径 |
--output |
否 | ../output |
JSON 输出文件目录 |
--target-dir |
否 | ../repos |
仓库克隆目录 |
--java-jar |
否 | java-parser/target/java-parser-0.0.1-SNAPSHOT.jar |
已构建 JAR 的路径 |
--no-clone |
否 | false |
跳过克隆,使用已有本地目录 |
--skip-java-check |
否 | false |
跳过 JAR 存在性预检 |
仓库被克隆到 repos/ 目录。提取的 JSON 文件输出到 output/ 目录,命名格式为:
{仓库名}_uml_{时间戳}.json
输出示例(节选):
{
"class": "GraphLinksModel",
"nodeDataArray": [
{
"key": 1,
"name": "User",
"stereotype": "Class",
"packageName": "com.example.model",
"properties": [
{ "name": "id", "type": "number", "visibility": "public" }
],
"methods": [
{
"name": "getName",
"parameters": [],
"type": "string",
"visibility": "public"
}
],
"loc": "245 120"
}
],
"linkDataArray": [
{ "from": 1, "to": 2, "relationship": "inheritance" }
]
}这是一个有意的多语言架构设计。Python 擅长脚本编写、CLI 交互和操作系统级操作(Git、子进程管理)。而 Java 借助 JavaParser 提供了目前最成熟、最准确的 Java AST 解析能力。与其使用基于 Python 的 Java 解析器(往往不够完整或无人维护),本项目选择让每种语言各展所长,通过简单的子进程 + JSON 契约进行通信。
Java 引擎使用 JavaParser 的完整 AST 解析器,而非正则表达式或逐行扫描。这使其能够正确处理:
- 多行注解和泛型
- 嵌套类与内部类型
- 跨文件的复杂 import 解析
- 所有 Java 可见性修饰符(public/protected/private/package-private)
代价是速度——AST 解析比正则匹配慢——但对于一个输出将被用于分析和数据集的工具来说,正确性是必不可少的。
ProjectAnalyzer 配置了 CombinedTypeSolver,同时包含 ReflectionTypeSolver(处理 JDK 类型)和 JavaParserTypeSolver(处理项目内类型)。这使得关系检测能够解析出 UserService 依赖 UserRepository,即使它们位于不同文件中、仅通过 import 语句关联。
输出 JSON 遵循 GoJS GraphLinksModel 架构,将节点和连线分为两个数组。这种格式:
- 可被 GoJS 直接消费以进行交互式图表渲染
- 易于转换为其他格式(如 Graphviz 的 DOT、Mermaid、PlantUML)
- 将类图自然地表示为数学图,便于数据集构建
UmlVisitor 为每个节点分配随机 (x, y) 坐标。这避免了所有节点在可视化工具中堆叠在 (0, 0) 处而需要手动解开的困扰。下游消费者可以应用布局算法(力导向、层次布局等)来覆盖这些位置。
- 接口与枚举支持 — 当前所有节点的构造型均为
"Class";区分接口、枚举和抽象类将提高准确性 - 更多 UML 关系类型 — 组合与聚合关系(当前仅检测继承、实现、关联和依赖四类)
- 注解提取 — AST 访问器已经可以获取注解信息;在输出中呈现
@Entity、@Service、@Autowired等 - 泛型类型保留 —
baseTypeName()目前会剥离泛型信息;保留参数化类型可增加信息完整度 - 增量分析 — 仅重新解析自上次运行以来发生变化的文件
- 多语言支持 — 架构支持在统一的 Python 编排层后接入更多语言解析器(如 Kotlin 或 Python AST 引擎)
- 并行文件解析 —
.java文件目前为顺序解析;采用并行流或虚拟线程可提速大型项目
📦 GitHub 仓库 · 欢迎 Star ⭐ 和 PR