Collections.synchronizedXXX() and internal mutex (aka SyncRoot)
Stuart Marks
stuart.marks at oracle.com
Fri May 1 22:45:40 UTC 2020
On 5/1/20 2:02 AM, dmytro sheyko wrote:
> The checked, synchronized and unmodifiable wrappers in some cases store backing
> collection in more than one fields.
>
> Thus `UnmodifiableList<E>` has
> 1. its own field `List<? extends E> list` and
> 2. `Collection<? extends E> c`, which it inherits from `UnmodifiableCollection<E>`.
>
> Also `UnmodifiableNavigableSet<E>` has even 3 duplicated fields:
> 1. its own `NavigableSet<E> ns`,
> 2. `SortedSet<E> ss` from `UnmodifiableSortedSet<E>` and
> 3. `Collection<? extends E> c` from `UnmodifiableCollection<E>`.
>
> Isn't it worth to get rid of such duplication? (at least for unmodifiable
> collections). This may affect serialization, but I believe it's still possible
> preserve serialization backward compatible, if it's necessary.
> Or is it done intentionally?
Interesting. I went through some of the history here, in particular the
core-libs-dev review threads of JDK-7129185 [1] which was the last time
significant work was done on the wrappers. There was no mention of the duplicate
references in any of the reviews. I suspect the wrappers introduced in this
changeset (e.g., UnmodifiableNavigableSet) copied the style from existing
wrappers, which also used this style.
I was able to look through the old (non open source) history of the JDK, and I
found that this style of having a redundant field in a wrapper subtype was
introduced in JDK 1.2 in 1998 along with the original collections implementation.
I suspect it was done this way for convenience. Certainly the wrapper subclasses
have access to the field from the superclass. But to use it they there would
have to be a cast at every call site that wanted to use a subclass method. This
would certainly make the wrapper code more verbose, and it might even slow
things down a bit with checkcast bytecodes and such.
While trying to save space is laudable, compatibility with existing serial forms
needs to be preserved. Doing this would require adding serialPersistentFields
arrays and readObject() and writeObject() methods to every one of the wrapper
classes. This is fairly tedious and error-prone. I'm not sure it's worth it.
s'marks
[1] https://bugs.openjdk.java.net/browse/JDK-7129185
More information about the core-libs-dev
mailing list