美文网首页
List#subList和Spring#split的使用陷阱

List#subList和Spring#split的使用陷阱

作者: 一只白羊座的猫 | 来源:发表于2019-02-16 15:56 被阅读0次

    前言

    如果Java应用程序出现了内存泄露,千万别着急着把应用杀掉,而是要保存现场。如果是互联网应用,可以把流量切到其他服务器。保存现场的目的就是为了把 运行中JVM的heap dump下来。

    正文

    裁剪List的时候这样子使用的话就会有一个引发内存泄漏的陷阱:

        myList = myList.subList(fromIndex, toIndex);
    

    特别是在循环调用的时候。

    来看看源码一探究竟:

        public List<E> subList(int fromIndex, int toIndex) {
            subListRangeCheck(fromIndex, toIndex, size);
            return new SubList(this, 0, fromIndex, toIndex);
        }
    
        SubList(AbstractList<E> parent,
                int offset, int fromIndex, int toIndex) {
            this.parent = parent;
            this.parentOffset = fromIndex;
            this.offset = offset + fromIndex;
            this.size = toIndex - fromIndex;
            this.modCount = ArrayList.this.modCount;
        }
    

    new出的SubList里保留着一份父引用。

    同样,在Stringsplit里,它最终会调用到String#substring

        new String(value, beginIndex, subLen);
    

    这里同样传了一份父引用value进去。

    是否Bug

    为了避免内存拷贝、加快速度,Sun JDK直接复用了原String对象的char[],偏移量和长度来标识不同的字符串内容。也就是说,subString出来的String小对象 仍然会指向原String大对象的char[]split也是同样的情况。

    虽然,subStringsplit的实现造成了现在的问题,但是这能否算String类的bug呢?个人觉得不好说。因为这样的优化是比较合理 的,subStringspit的结果肯定是原字符串的连续子序列。只能说,String不仅仅是一个核心类,它对于JVM来说是与原始类型同等重要的 类型。

    JDK实现对String做各种可能的优化都是可以理解的。但是优化带来了忧患,我们程序员足够了解他们,才能用好他们。

    参考

    分析内存泄露的一般步骤

    相关文章

      网友评论

          本文标题:List#subList和Spring#split的使用陷阱

          本文链接:https://www.haomeiwen.com/subject/ysxieqtx.html