使用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--;
        }
    }
相关推荐
Bs_MoneyMagnet2 分钟前
基于springboot+vue的爱心众筹系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·管理系统
AIFQuant4 分钟前
Python股票实时价格告警系统:WebSocket订阅与REST快照实战
开发语言·python·websocket·a股行情
wuyk55515 分钟前
从零吃透 MQTT 通信|第 10 章 阿里云 / 腾讯云 MQTT 设备完整对接实战,三元组、签名、设备上云调试
c语言·开发语言·stm32·学习·阿里云·云计算·腾讯云
名字还没想好☜16 分钟前
Java Collectors.groupingBy 进阶:多级分组、下游收集器与统计聚合一次搞定
java·windows·后端·python·spring
Wang's Blog20 分钟前
Java框架快速入门: Spring Security+OAuth2之前端按钮级安全与路由守卫
java·安全·spring
ocean210338 分钟前
2025-2026年Java语言及生态面试高频知识点洞察
java·开发语言·面试
2302_11144 分钟前
java时间类型
java·开发语言
用户8181870627461 小时前
第25章 Redis集群脑裂实录:一次真实故障复盘
java·后端
运行时异常1 小时前
【WMS 仓储系统集成 AI Agent 实战】第 6 讲:RAG 知识库——“输出简单流程“为什么检索不到任何东西
java