java中快速失败机制的“Bug”

本文主要探讨Java中集合删除元素时失败机制的漏洞。以ArrayList和LinkedList为例,分析了在删除特定位置元素(ArrayList删除倒数第二个、LinkedList删除倒数第一或第二个)时不报错的原因,涉及到集合内部类对hasNext()方法的重写及相关判断逻辑。
	之前的文章中对java中的Fast-Fail机制进行过简单的介绍,笔者在后来的学习中发现了这个机制的一点漏洞,特此补充下,
	如有不解,可看上篇文章

地址

失败机制的漏洞

这个漏洞要分为2部分讲:
1)ArrayList
在ArrayList中删除倒数第二个元素时不会报错,ArrayList中定义了一个私有内部类来实现Iterator接口,并对hasNext()方法进行了重写,部分源代码如下:

 private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;

        Itr() {}

        public boolean hasNext() {
            return cursor != size;
        }

在这里有一个变量名为cursor,也就是游标,它总是指向当前索引的下一个索引,在删除倒数第二个索引时,在hasNext()方法中会进行判断,假设集合有5个元素,则就是判断4!=4,显然返回false,就不会进入循环调用下一个.next()方法,更不会进行expectedModCount = modCount的判断

public E next() {
            checkForComodification();
            if (!hasNext())
                throw new NoSuchElementException();

            lastReturned = next;
            next = next.next;
            nextIndex++;
            return lastReturned.item;
        }

在next()方法中会调用checkForComodification()方法进行检查

final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }

也就不会抛出异常

2)LinkedList
在LinkedList中删除倒数第一个或者倒数第二个元素时均不会报错,LinkedList中同样定义了一个私有内部类,但其实现的接口为ListIterator,对hasNext()方法进行了重写,部分源代码如下:

private class ListItr implements ListIterator<E> {
        private Node<E> lastReturned;
        private Node<E> next;
        private int nextIndex;
        private int expectedModCount = modCount;

        ListItr(int index) {
            // assert isPositionIndex(index);
            next = (index == size) ? null : node(index);
            nextIndex = index;
        }

        public boolean hasNext() {
            return nextIndex < size;
        }

可见此时hasNext()的判断条件变为了nextIndex < size,这个时候同样假设集合中有5个元素,则在删除倒数第一个或第二个元素时的判断条件为4<4以及5<4,显然返回false,之后的就不用我多说了吧跟上面一样不会进入下一次循环从而不会进行检查更不会抛出异常 !

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值