📌 作者介绍
哈喽,我是 CodeStats。
一个在底层技术上"考古"了四年的硬核爱好者,也是 WWAIC(全周项目AI编程 ) 范式的提出者和实践者。我曾手写过一个完整的Java Web框架(从IoC容器到嵌入式Tomcat,代码全开源),也喜欢用通俗的语言拆解CPU、JVM、操作系统的运行本质。
我一直相信,计算机科学没有魔法。所有看似神奇的效果------无论是java -jar一键启动,还是多线程自动切换------底层都是简单的规则层层组合
一、引言
在 Java 后端开发中,Spring 生态已然成为事实标准。然而,当我们亲手实现一个微型 Spring + Tomcat 时,才能真正理解 IoC 容器如何管理 Bean、DispatcherServlet 如何分发请求、连接池如何限流。
CodeStats 正是一个完全自研的"类 Spring"框架,它集成了 IoC 容器、MVC 架构、嵌入式 Tomcat、JDBC 连接池、MyBatis 风格 Mapper 以及代码分析引擎。
更值得一提的是,CodeStats 是 WWAIC(Whole-Week AI Engineering,全周项目 AI 工程) 范式的首个实证项目------100% 由 AI 生成,耗时仅一周,实现了从 IoC 容器到嵌入式 Tomcat 的全栈能力。
今天,我将带你深入 CodeStats 最新实现的 3D 实时监控模块,看看如何用 Three.js + Java 打造一个"系统时空穿梭机"!
二、CodeStats 项目介绍
2.1 一分钟快速启动
bash
# 下载并解压
unzip CodeStats-1.0.zip && cd CodeStats
java -jar CodeStats-1.0.jar
# 浏览器访问 http://localhost:28080/
无需任何配置------不配置数据库,核心功能完整可用。
2.2 技术架构全景
CodeStats 从 Socket 开始,手写了整套基础设施:
| 模块 | 自研实现 | 说明 |
|---|---|---|
| Web 容器 | BIO/NIO 线程池 + Pipeline-Valve 责任链 | 模拟 Tomcat 架构 |
| IoC 容器 | 包扫描 + 反射注入 + 单例池 | @Controller/@Service/@Autowired |
| MVC 框架 | DispatcherServlet + HandlerMapping + 参数绑定 | @RequestMapping/@ResponseBody |
| ORM 框架 | MapperProxy 动态代理 + 注解 SQL | @Mapper/@Select,自动映射结果 |
| 连接池 | 阻塞队列 + Semaphore 并发控制 | 支持空闲回收、连接验证 |
| 日志框架 | Appender + Layout + XML 配置 | 异步/滚动文件/级别过滤 |
| 缓存框架 | ConcurrentHashMap + TTL + 定期清理 | 可选 Caffeine 扩展 |
| 前端框架 | Proxy + Dep + Watcher 响应式系统 | 自研类 Vue 框架 SimpleVue |
2.3 功能矩阵
CodeStats 不仅是一个框架,更是一套完整的开发工具集:
-
代码分析引擎:多线程并行统计(总行数、代码行、注释行、空行、复杂度),支持 GitIgnore 过滤、扩展名筛选、排除路径,提供 Web 界面 / Swing GUI / 命令行 三种模式
-
目录管理:树形导航、文件/目录 CRUD、文本在线编辑、目录打包 ZIP 下载
-
AI Agent:Ollama 本地模型、DeepSeek API、自定义 API、内置知识库"项目助手"
-
数据库浏览器:连接 MySQL,动态加载数据库/表/列信息
三、3D 实时监控:设计思路
3.1 为什么需要 3D 实时监控?
传统的系统监控面板以表格和 2D 图表为主,信息密度高但缺乏空间感。3D 可视化可以将线程状态、内存使用、连接池、请求统计等多维数据在同一个三维空间中呈现,让系统状态一目了然。
3.2 整体架构
text
┌─────────────────────────────────────────────────────────────┐
│ 前端 (Three.js) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ 3D 线程图 │ │ 内存柱状图 │ │ 粒子流调用链展示 │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ ↕ REST API │
├─────────────────────────────────────────────────────────────┤
│ 后端 (Java / CodeStats) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ JvmMonitorService │ │
│ │ • ThreadMXBean 采集线程状态 │ │
│ │ • Runtime 采集内存信息 │ │
│ │ • DataSourceUtils 采集连接池状态 │ │
│ │ • TraceContextHolder 采集请求调用链 │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
3.3 数据采集层(后端)
后端核心是 JvmMonitorService,它聚合了四类数据:
-
线程状态 :通过
ThreadMXBean获取所有线程的运行状态(RUNNING/BLOCKED/WAITING 等) -
内存信息 :通过
Runtime获取堆内存和非堆内存使用情况 -
连接池状态 :通过
DataSourceUtils.getPoolStats()获取活跃/空闲连接数 -
请求调用链 :通过
TraceContextHolder获取每个请求的调用链路
3.4 可视化层(前端)
前端基于 Three.js 构建 3D 场景,包含四大可视化组件:
-
线程柱状图:不同颜色代表不同线程状态,柱高代表数量
-
内存环形图:堆内存和非堆内存的占用比例
-
连接池水位图:动态显示连接池的活跃/空闲情况
-
粒子流调用链:实时展示最新活跃线程的方法调用链路
四、核心代码片段
4.1 后端:线程详情采集(含 lastActiveTime)
java
// JvmMonitorService.java
private List<Map<String, Object>> getThreadDetails() {
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long[] allThreadIds = threadMXBean.getAllThreadIds();
ThreadInfo[] infos = threadMXBean.getThreadInfo(allThreadIds, 20);
Map<Long, TraceContextHolder.TraceContext> contextMap =
TraceContextHolder.getAllContexts();
List<Map<String, Object>> details = new ArrayList<>();
for (ThreadInfo info : infos) {
if (info == null) continue;
Map<String, Object> item = new LinkedHashMap<>();
long tid = info.getThreadId();
item.put("threadId", tid);
item.put("threadName", info.getThreadName());
item.put("state", info.getThreadState().name());
TraceContextHolder.TraceContext ctx = contextMap.get(tid);
String callChain = null;
String status = "IDLE";
long lastActiveTime = 0;
if (ctx != null) {
if (ctx.endTime == 0) {
status = "RUNNING";
lastActiveTime = System.currentTimeMillis();
callChain = ctx.nodePath != null ? ctx.nodePath : "Dispatcher";
} else {
status = "COMPLETED";
lastActiveTime = ctx.endTime;
callChain = ctx.nodePath != null ? ctx.nodePath : "Completed";
}
}
item.put("callChain", callChain != null ? callChain : "");
item.put("status", status);
item.put("lastActiveTime", lastActiveTime); // ★ 关键排序字段
if ("RUNNING".equals(status) && callChain != null) {
String[] nodes = callChain.split(" → ");
item.put("nodes", nodes);
} else {
item.put("nodes", new String[0]);
}
details.add(item);
}
return details;
}
4.2 后端:聚合监控数据接口
java
// JvmMonitorService.java
public Map<String, Object> getAggregatedMonitorData() {
Map<String, Object> result = new HashMap<>();
result.put("threads", getAllThreadsInfo()); // 线程统计
result.put("memory", getMemoryInfo()); // 内存信息
result.put("pool", DataSourceUtils.getPoolStats()); // 连接池
result.put("requests", getRequestStats()); // 请求统计
result.put("threadDetails", getThreadDetails()); // ★ 线程详情
return result;
}
4.3 前端:线程排序与粒子流更新
javascript
// realtime-monitor.js - 核心排序逻辑
function updateScene(data) {
// 按状态优先级 + 时间降序排序
const statusPriority = {
'RUNNING': 1, // 运行排第一
'BLOCKED': 2, // 阻塞排第二
'WAITING': 3,
'TIMED_WAITING': 4,
'NEW': 5,
'TERMINATED': 6,
'IDLE': 7,
'COMPLETED': 8
};
const sortedThreads = [...data.threadDetails].sort((a, b) => {
const priA = statusPriority[a.status] || 9;
const priB = statusPriority[b.status] || 9;
if (priA !== priB) return priA - priB;
const timeA = a.lastActiveTime || a.startTime || 0;
const timeB = b.lastActiveTime || b.startTime || 0;
return timeB - timeA; // 降序,最新在前
});
// 线程列表使用排序后的数据
renderThreadList(sortedThreads);
// 粒子流使用排序后的数据(取第一条线程的调用链)
if (cleanupThreadFlow) {
updateThreadFlowData(sortedThreads);
}
}
4.4 前端:粒子流节点动态渲染
javascript
// thread-flow-module.js
function renderThreadFlows(threads) {
clearGraph(); // 清空旧节点和连线
const firstThread = threads[0];
let nodeNames = firstThread.nodes || [];
// 如果 nodes 为空,从 callChain 解析
if (!nodeNames || nodeNames.length === 0) {
if (firstThread.callChain) {
nodeNames = firstThread.callChain.split(' → ')
.map(s => s.trim()).filter(s => s.length > 0);
}
}
const nodeCount = nodeNames.length;
// ★ 根据节点数量动态生成位置
const positions = generateNodePositions(nodeCount, -6, 6, 0);
// 为每个节点创建球体 + 标签
for (let i = 0; i < nodeCount; i++) {
const sphere = new THREE.Mesh(sphereGeo, material);
sphere.position.copy(positions[i]);
sphere.userData = { nodeName: nodeNames[i] };
nodesGroup.add(sphere);
// 添加 CSS2D 标签...
}
// 节点 > 1 时,绘制连线和粒子流
if (nodeCount > 1) {
// 绘制连线...
// 创建粒子系统沿路径流动...
}
}
4.5 核心:动态生成节点位置(起点固定)
javascript
function generateNodePositions(nodeCount, startX = -6, endX = 6, y = 0) {
const positions = [];
if (nodeCount === 0) return positions;
if (nodeCount === 1) {
positions.push(new THREE.Vector3(0, y, 0)); // 单节点居中
return positions;
}
// 多节点均匀分布,第一个节点固定在 startX
for (let i = 0; i < nodeCount; i++) {
const t = i / (nodeCount - 1);
const x = startX + t * (endX - startX);
const z = Math.sin(i * 1.3) * 0.4; // 轻微 Z 轴错落
positions.push(new THREE.Vector3(x, y, z));
}
return positions;
}
五、效果展示

如上图所示,3D 实时监控大屏包含:
| 区域 | 内容 |
|---|---|
| 左侧 3D 场景 | 线程柱状图(颜色区分状态)、内存环形图、连接池水位 |
| 右侧线程列表 | 按运行/阻塞优先 + 时间最新排序,展示线程 ID、名称、状态、调用链 |
| 底部粒子流 | 实时展示最新活跃线程的方法调用链路,节点数动态变化,粒子沿路径流动 |
| 请求统计 | 总请求数、运行中、错误数、平均响应时间、最近请求 |
六、项目地址与资源
6.1 开源仓库
Gitee 开源仓库: https://gitee.com/zhouzuoli/code-stats.git
6.2 快速体验
bash
git clone https://gitee.com/zhouzuoli/code-stats.git
cd code-stats
java -jar CodeStats-1.0.jar
# 访问 http://localhost:28080/
# 点击顶部导航栏 「3D 依赖图」→「实时监控」
6.3 相关文章
七、总结
CodeStats 的 3D 实时监控模块展示了从自研 Java 框架到三维可视化的完整链路:
-
后端:通过 JMX 和自研 TraceContext 采集线程、内存、连接池、调用链数据
-
排序逻辑:运行/阻塞优先 + lastActiveTime 降序,确保最新活跃线程排在最前
-
前端:Three.js 构建 3D 场景,粒子流动态展示调用链,节点数量随调用链长度动态变化
-
起点固定:第一个节点始终固定在左侧,便于观察调用链的起始位置
如果你也想拥有一个属于自己的 Java 框架,或者需要一个轻量级的系统监控工具,不妨 Clone 下来试试。有任何问题欢迎在评论区留言!