山大软院创新实训易学探索助手---个人报告(五)
测试和问题描述
本周我对系统进行了多项测试,其中包括在极端条件下的系统性能测试,发现了一个潜在风险并进行了修复,具体问题及修复过程如下。
在开发系统时,我设计了一个TaskService 服务,用于管理异步任务的创建、查询和状态更新。
task相关核心代码如下:
@Service
public class TaskService {
private final Map<String, Task> tasks = new ConcurrentHashMap<>();
public String createTask() {
String taskId = "TASK-" + System.currentTimeMillis();
tasks.put(taskId, new Task(taskId));
return taskId;
}
// 其他方法:getTask、updateResult、deleteTask
}
潜在风险
- 内存泄漏:所有任务对象(
Task)均存储在ConcurrentHashMap中,若不主动删除已完成的任务,随着时间推移,内存占用将持续增长。 - OOM 风险:在高频任务创建场景下(如每秒生成数百个任务),堆内存可能快速耗尽,导致
OutOfMemoryError。
一、内存泄漏复现与测试
测试代码
为了验证内存泄漏问题,编写了一个模拟无限创建任务的测试程序:
public static void main(String[] args) {
TaskService taskService = new TaskService();
while (true) {
taskService.createTask(); // 持续创建任务,不删除
}
}
测试过程
- 启动测试程序:运行上述
main方法,持续创建任务。 - 监控工具:使用
JConsole连接 JVM 进程,观察内存变化。
测试结果
- 内存趋势:堆内存使用量随时间不断增长(如下图所示)。

- 最终结果:约 20 分钟后抛出
java.lang.OutOfMemoryError: Java heap space。
二、性能优化方案
1. 问题根因分析
- 数据生命周期失控:任务完成后未及时清理,
ConcurrentHashMap长期持有对象引用。 - 缺乏自动回收机制:依赖业务代码显式调用
deleteTask,易遗漏。
2. 优化方案:定时清理已完成任务
通过 Spring Boot 的定时任务功能,定期清理所有状态为 DONE 的任务。
代码实现
import org.springframework.scheduling.annotation.Scheduled;
@Service
public class TaskService {
private final Map<String, Task> tasks = new ConcurrentHashMap<>();
// 每5分钟清理一次已完成的任务
@Scheduled(fixedRate = 5 * 60 * 1000)
public void autoCleanTasks() {
int initialSize = tasks.size();
tasks.entrySet().removeIf(entry ->
Task.Status.DONE.equals(entry.getValue().getStatus())
);
System.out.printf("已清理任务:%d → %d(删除 %d 个)%n",
initialSize, tasks.size(), initialSize - tasks.size());
}
}
关键配置
- 在 Spring Boot 主类添加
@EnableScheduling注解:@SpringBootApplication @EnableScheduling // 启用定时任务 public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
3. 方案优势
- 自动化:无需业务代码主动触发,降低人为遗漏风险。
- 可控性:通过
fixedRate参数灵活调整清理频率(如生产环境可设置为 1 小时)。 - 低开销:
ConcurrentHashMap的遍历操作线程安全且高效。
三、优化效果验证
测试场景
- 模拟正常业务:持续创建任务,并为每个任务随机设置完成状态。
- 监控指标:堆内存使用量、GC 频率、任务清理日志。
测试结果
- 内存趋势:堆内存周期性波动,无持续增长。
- 日志输出:
已清理任务:1520 → 320(删除 1200 个) 已清理任务:1800 → 250(删除 1550 个) - OOM 问题解决:长时间运行(24 小时)未发生内存溢出。
四、总结
关键结论
- 问题定位:未清理的已完成任务导致内存泄漏是 OOM 的直接原因。
- 优化效果:定时清理机制使内存使用从持续增长变为周期性释放,彻底解决溢出风险。
- 方法论:内存管理需结合业务场景设计数据生命周期,并借助自动化机制保障。
通过本次实践,我们不仅解决了一个典型的内存泄漏问题,更强化了对资源生命周期管理的意识。在分布式系统和高并发场景下,类似问题需通过 代码设计 + 监控告警 + 自动化回收 的组合拳来系统性规避。相信我在本次发现问题后能够积累相关经验,在之后开发项目的过程中注重内存的相关问题。

浙公网安备 33010602011771号