使用mat 分析java OOM问题

1.使用MAT打开oom-facilityservice.hprof文件

2.生成 内存泄漏报告

3.查看泄露详情

4.分析报告

5.通过报告可以看出有一个List大小为2个G,并且

复制代码
 at com.huawei.drms.facilitymgmtservice.domain.odn.service.impl.OdnRelationDomainServiceImpl.queryUpByDevice(Ljava/util/List;Ljava/util/List;)Ljava/util/List; (OdnRelationDomainServiceImpl.java:102
在这个地方
6.分析代码
1.先分析
queryUpByDevice方法
可以看出这个查询入参为deviceIds和sources,一次查询应该不可能查出2个G的内容
service

在调用

复制代码
queryUpByDevice,向list<OdnRelationPo> 中添加数据,这是就可以确定,八成是递归方法没有推出导致的。
java 复制代码
 private void odnQueryUp(List<OdnPointPo> pointPos, String deviceId) {
        String currentDeviceId = deviceId;
        while (true) {
            List<String> source = Arrays.asList(OdnRelationSourceEnum.UP.getCode(),
                OdnRelationSourceEnum.FULL.getCode());
            List<OdnRelationPo> odnRelPos = odnRelationDomainService.queryUpByDevice(
                Collections.singletonList(currentDeviceId), source);

            if (CollectionUtils.isEmpty(odnRelPos)) {
                break;
            }
            OdnRelationPo odnRelPo = odnRelPos.get(0);
            if (StringUtils.isNotEmpty(odnRelPo.getADeviceId())) {
                pointPos.add(0, new OdnPointPo(odnRelPo, "A"));
                currentDeviceId = odnRelPo.getADeviceId();
            } else {
                break;
            }
        }
    }

修改后

java 复制代码
 private void odnQueryUp(List<OdnPointPo> pointPos, String deviceId) {
        // 死循环现在最大查询20次
        int limit = 20;
        List<String> usedDeviceIds = new ArrayList<>();

        String currentDeviceId = deviceId;
        List<String> source = Arrays.asList(
            OdnRelationSourceEnum.UP.getCode(),
            OdnRelationSourceEnum.FULL.getCode()
        );
        List<OdnRelationPo> odnRelPos;
        while (limit > 0) {
            if (usedDeviceIds.contains(currentDeviceId)) {
                // 已经查询过了,代表当前路径是个环,退出
                break;
            }
            usedDeviceIds.add(currentDeviceId);

            odnRelPos = odnRelationDomainService.queryUpByDevice(
                Collections.singletonList(currentDeviceId), source);
            if (CollectionUtils.isEmpty(odnRelPos)) {
                // 数据为空,退出
                break;
            }

            OdnRelationPo odnRelPo = odnRelPos.get(0);
            if (StringUtils.isNotEmpty(odnRelPo.getADeviceId())
                && !currentDeviceId.equals(odnRelPo.getADeviceId())) {
                // 更换查询条件
                pointPos.add(0, new OdnPointPo(odnRelPo, "A"));
                currentDeviceId = odnRelPo.getADeviceId();
            } else {
                break;
            }

            limit--;
        }
    }
相关推荐
OPEN-F几秒前
Python进阶教程:单元测试与代码质量
开发语言·python·单元测试
阿里嘎多学长1 分钟前
2026-08-20 GitHub 热点项目精选
开发语言·程序员·github·代码托管
野生技术架构师4 分钟前
Spring Boot 实现数据脱敏:自定义注解 + Jackson 序列化器
java·spring boot·后端
其实防守也摸鱼10 分钟前
Codex破局:前端组件秒级生成的技术文章大纲
开发语言·前端·人工智能·学习·安全·web安全
AI人工智能+电脑小能手11 分钟前
大白话说Java设计模式-28-模板方法模式(业务实战篇)
java·设计模式·模板方法模式·spring源码·订单系统·代码复用
奥莱维14 分钟前
KNX酒店方案_KNX专用线与高端酒店技术逻辑
java·服务器·前端·数据库
Logintern0921 分钟前
装饰器和洋葱模式的区分
开发语言·python·架构
工业一体机老司机23 分钟前
Linux工业一体机自启动服务配置:systemd服务单元编写与开机优化实战
java·linux·服务器
冻柠檬飞冰走茶36 分钟前
《数据结构实验指导-C++语言版》 在顺序表 list 中查找元素 x
开发语言·数据结构·c++·算法·list
Brilliantwxx37 分钟前
【C++】 高阶数据结构图(1)并查集
开发语言·数据结构·c++