使用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--;
        }
    }
相关推荐
Flynn Liang19 分钟前
Agentic 工作流:子代理、Supervisor 与人工介入
java·langchain·多智能体·supervisor·agentic·langchain4j
xys_67823 分钟前
JavaSE通关手册:运算符
java·java-ee
starzy199041 分钟前
深入理解Scala隐式值:编译期自动装配
开发语言·后端·scala
布莱克6051 小时前
Swift 条件语句详解:从 if 到 switch 的完整指南
开发语言·ssh·swift·switch·条件语句·guard·if
吴可可1231 小时前
ActiveX调用WScript.Shell原理揭秘
开发语言
jyOverQ1 小时前
从零学 JVM(七):垃圾收集器详解——Serial、ParNew、Parallel、CMS 与 G1
java·jvm
liangbo71 小时前
Spring系列11:切点表达式
java·spring
3095566662 小时前
股票接口返回 404 与空数组的排查笔记:证书状态与级别参数
java·笔记·python·ios·iphone·股票数据api·股票数据接口
nice_lcj5202 小时前
MySQL 存储引擎入门:InnoDB 和 MyISAM 到底怎么选
java·数据库·mysql·面试·innodb·存储引擎·myisam
文丑颜不良啊2 小时前
LeetCode2861~2880题目解析
java·leetcode