使用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--;
        }
    }
相关推荐
行者全栈架构师1 小时前
Maven dependency:tree 的 8 个高级用法
java·后端
行者全栈架构师5 小时前
IDEA 中 Maven 项目的 15 个红色报错快速解决方法
java·后端
令人头秃的代码0_05 小时前
mac(m5)平台编译openjdk
java
唐青枫1 天前
Java JDBC 实战指南:从 Connection 到事务和连接池
java
一个做软件开发的牛马1 天前
MyBatis-Plus 从零实战:完整搭建可运行 Demo,BaseMapper 零 SQL、Wrapper 条件构造、分页插件与代码生成器详解
java·后端
用户3721574261351 天前
Java 处理 PDF 图片:提取 PDF 中的图片,并压缩 PDF 图片体积
java
用户3721574261351 天前
Java 打印 Word 文档:从基础打印到高级设置
java
用户3521802454752 天前
当 Prompt 学会"热更新":Spring Boot × Nacos3 AI 实战
java·spring boot·ai编程
东坡白菜2 天前
破局全栈:一个前端开发的Java入门实战记录(1)
java·全栈
唐青枫2 天前
Java Tomcat 实战指南:从 Servlet 容器到 Spring Boot 部署
java