55 处理错误的树形数据结构导致不断地添加元素到集合中 OOM

Posted 蓝风9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了55 处理错误的树形数据结构导致不断地添加元素到集合中 OOM相关的知识,希望对你有一定的参考价值。

前言

呵呵 这是最近一个 前同事/朋友 碰到的一个问题 

主要的问题是 在 dump 文件中发现了很多 LinkedList$Node 的节点 

然后 整个问题 抛出来的错误是 OOM 

呵呵 这种问题 还是相当好处理的 

这里 仅仅是 简单记录一下 

前因

后果

测试用例

/**
 * Test11OomByTree
 *
 * @author Jerry.X.He <970655147@qq.com>
 * @version 1.0
 * @date 2022-07-07 22:04
 */
public class Test11OomByTree 

    /**
     * 模拟数据源
     */
    public static Map<Long, Tree> dataSource = new HashMap<>();

    //准备数据
    static 
        //循环数据
        Tree parent = new Tree(1L, "父类", 2L);
        Tree son = new Tree(2L, "子类", 1L);

        dataSource.put(parent.getId(), parent);
        dataSource.put(son.getId(), son);
    

    // -Xms128M -Xmx128M -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/Users/jerry/IdeaProjects/HelloWorld/target/Test11OomByTree.hprof
    public static void main(String[] args) 
        //入参
        Tree param = new Tree(1L, "父类", 2L);
        //返回
        List<Tree> vos = new LinkedList<>();

        while (null != param.getParentId()) 
            Tree parent = getTreeByParentId(param.getParentId());
            vos.add(parent);
            //死循环
            param = parent;
        
    


    /**
     * mock查询方法
     *
     * @param parentId
     * @return
     */
    public static Tree getTreeByParentId(Long parentId) 
        return dataSource.get(parentId);
    

    /**
     * 树状结构类
     */
    static class Tree 

        /**
         * id
         */
        private Long id;

        /**
         * 名称
         */
        private String name;

        /**
         * 父类ID
         */
        private Long parentId;

        public Tree(Long id, String name, Long parentId) 
            this.id = id;
            this.name = name;
            this.parentId = parentId;
        

        public Long getId() 
            return id;
        

        public void setId(Long id) 
            this.id = id;
        

        public String getName() 
            return name;
        

        public void setName(String name) 
            this.name = name;
        

        public Long getParentId() 
            return parentId;
        

        public void setParentId(Long parentId) 
            this.parentId = parentId;
        
    


现象为 最终产生 OOM 

堆 dump 文件可以使用 jvisualVM 或者 jhat 或者 sa 自己处理 都行 

我们这里以 jhat 为例, 最常见 适用的场景最多 

dump 文件分析

jvisualVM 的 class stats 结果

jhat 的 class stats 

从这个问题 反推也很简单 

抽样 是来一个 LinkedList$Node, 然后 查看一下 这些 Node 指向的对象, 然后 再结合业务代码 看一下 多半问题就出来了 

这里随便抽样几个 

 

 

可以看到的是 随便抽样了 五个 LinkedList$Node

其中三个 指向的是 com.hx.test13.Test11OomByTree$Tree@0x7bcdd4888 (40 bytes)

两个指向的是 com.hx.test13.Test11OomByTree$Tree@0x7bcdcc8a8 (40 bytes)

然后 分别点击 这两个 oop 查看详情

可以看到的是 一个 oop 为类型为  Test11OomByTree$Tree 的 name 为 “父类” 的节点, 一个是 Test11OomByTree$Tree 的name 为 "子类" 的节点 

然后 再根据 这些业务信息 结合业务代码 查找 即可找到问题的根源 

 

 完

以上是关于55 处理错误的树形数据结构导致不断地添加元素到集合中 OOM的主要内容,如果未能解决你的问题,请参考以下文章

向 uitableview 添加分隔符会导致布局约束错误

组合模式

组合模式

删除过滤的统计信息会导致死锁

php/Mysql 最好的树形结构

结构型模式-组合模式(树形结构的处理)