8

有一个内部类 SynchronizedCollection - 在 java.util.Collections 内部有两个构造函数。第一个接受集合,另一个接受集合和互斥锁。前构造函数检查参数是否为空。但后来不要!这是实现。

 SynchronizedCollection(Collection<E> c) {
        if (c==null)
            throw new NullPointerException();
        this.c = c;
        mutex = this;
  }
 SynchronizedCollection(Collection<E> c, Object mutex) {
        this.c = c;
        this.mutex = mutex;
 }

通过这个实现,我可以通过将 null 发送到第二个构造函数来打破类不变量。

我相信它应该是这样的:

 SynchronizedCollection(Collection<E> c) {
        this(c,this)
  }
 SynchronizedCollection(Collection<E> c, Object mutex) {
        if (c==null)
            throw new NullPointerException();
        this.c = c;
        this.mutex = mutex;
 }

但是我无法说服自己 Josh Bloch 和 Neal Gafter 看不到这一点。所以你真的能告诉我我在这里错过了什么吗?


编辑:可能的攻击

    Map<String, String> m = new Map<String, String>(){

        @Override
        public int size() {
            // TODO Auto-generated method stub
            return 0;
        }

                   .
                   .
                   .

        @Override
        public Collection<String> values() {
            return null;
        }


    };

    Map<String, String> synchronizedMap = Collections.synchronizedMap(m);
    Collection<String> values = synchronizedMap.values();
4

2 回答 2

12

当然这是一个错误。两个构造函数应该是一致的,要么都应该抛出异常,要么都不应该抛出异常。

这已在 Java 8 中修复。现在两个构造函数都会抛出异常:

SynchronizedCollection(Collection<E> c) {
    this.c = Objects.requireNonNull(c);
    mutex = this;
}

SynchronizedCollection(Collection<E> c, Object mutex) {
    this.c = Objects.requireNonNull(c);
    this.mutex = Objects.requireNonNull(mutex);
}
于 2013-09-29T16:29:06.557 回答
3

这两个构造函数都是包保护的,只有第一个可以通过 的和方法与null参数一起使用。public synchronizedList()synchronizedSet()Collections

另一个构造函数在内部(在Collections类中)使用,第一个参数永远不能null在各种实现(调用代码)中,所以你不能破坏它。

你总是可以尝试在java.util包中创建一些东西,但你很可能会得到一个SecurityException.

于 2013-09-29T16:19:08.793 回答