JDK-8145469 : deprecate legacy collections: Vector, Hashtable, etc.
Type:Sub-task
Component:core-libs
Sub-Component:java.util:collections
Priority:P3
Status:Open
Resolution:Unresolved
Submitted:2015-12-15
Updated:2018-09-11
The Version table provides details related to the release that this issue/RFE will be addressed.
Unresolved : Release in which this issue/RFE will be addressed. Resolved: Release in which this issue/RFE has been resolved. Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.
Deprecate the "legacy" collections using the new deprecation annotations. The legacy collections include Dictionary, Enumeration, Hashtable, Stack, and Vector.
Comments
Clearly Properties has its own set of messes and should be revisited. Deprecation isn't inherited, so Properties can continue to extend Hashtable as long as Hashtable is still around. (There is no proposal to remove Hashtable, only to deprecate it.)
A possible evolutionary direction for Properties would be change it to no longer extend Hashtable. It would still implement Map<Object,Object>. It could be reimplemented to contain (instead of inherit) a HashMap, with special handling for system properties that could be stored elsewhere. Several methods would have to be pulled down from Hashtable and reimplemented. This would strictly be an incomptible change, as Properties would no longer be assignment-compatible with Hashtable. I doubt that there are many uses like this, though; I suspect that most uses of Properties instances are used via a reference of type Properties.
The behavior of accepting any object as a key and a value will likely have to be preserved.
I'm not sure how much this would buy us. It would break the inheritance of Hashtable by Properties, which has long been viewed as a mistake, and which has been a recurring source of errors. Not sure whether that offsets the incompatibility risk.
24-09-2016
java.util.Properties should also get a close look. It extends Hashtable and is stuck with the "wrong" type arguments, Hashtable<Object,Object> when it is (almost?) always used with Strings.
However, we need a replacement for its functionality, and in particular for the System.getProperties method, which is pretty fundamental.
21-09-2016
In general, a point for deprecating old APIs (with forRemoval=false) is to encourage people not to write new code using them, and to migrate old code and APIs away from them where possible and appropriate. Essentially deprecating these APIs is making a stronger statement than was made by JDK-6583872, "Direct uninformed users away from Vector/Hashtable".
This revisits the decision made and documented in JDK-6201870. That decision was quite reasonable when it was made, but the comments there are now 11 years old. In particular, portability to pre-1.2 JDKs that lack the collections framework should really no longer be an issue. In addition, "deprecation" is being redefined by JEP 277 so that it doesn't imply the API will be removed unless that is explicitly annotated. Deprecation with forRemoval=false is similar to the old (much talked about, but never implemented) concept of "denigration," though probably not as gentle as was suggested in JDK-6201870.
While these old APIs aren't "actively harmful" they have some issues that make them difficult or error-prone to use if you move beyond the simplest cases.
There is the lack of concurrent modification checking with Enumeration.
Vector and Hashtable lock each call, but there are many cases where external locking is required. For example, iterating the contents, or searching and modifying a Vector by index. This embodies an uncomfortable programming style where locking is sometimes internal to the collection and sometimes external.
Internal synchronization causes a number of problems that are difficult or impractical to fix or that are only rarely are feasible to fix: JDK-5085747 JDK-6934356 JDK-6927486 JDK-6205425 JDK-6582568.
The class hierarchy shows poor modeling, sets a bad example, and can be confusing. For example: Stack extends Vector; Properties extends Hashtable, and in turn, java.security.Provider extends Properties. See JDK-4792384 JDK-4130830 JDK-6368455.
21-04-2016
Remi, in your example the Iterator itself is used in multiple threads, and that is never supported.
The List interface is fundamentally thread-hostile due to the access by index. We could recommend using a concurrent queue as a replacement for most uses.
The ability to lock these collections by synchronized enables arbitrary transactions, not supported by any other jdk collections.
synchronized (vector) { vector.remove("foo"); vector.add("bar"); }
21-04-2016
I was referring to the behavior of the Iterator itself,
test the following code:
public static void main(String[] args) throws InterruptedException {
Vector<Integer> v = new Vector<>();
v.add(42);
Iterator<Integer> it = v.iterator();
new Thread(() -> {
while(it.hasNext()) {
// do nothing
}
System.out.println("end");
}).start();
Thread.sleep(2_000);
it.next();
}
21-04-2016
Perhaps Remi is referring to the fact that Vector's iterator is not weakly consistent as would be the case for a truly concurrent collection, rather than a synchronized collection, which is what Vector is.
Arguably Vector is "safer" in this regard that a wrapping synchronized collection where explicit synchronization when iterating is required by the caller (as is the case for Vector with Enumeration).
21-04-2016
Martin, to be clear, deprecating them doesn't imply that they're going to be removed. See JEP 277 (JDK-8065614). These will be deprecated with forRemoval=false. Only when forRemoval=true is present does it mean that something will be removed.
R��mi, could you explain what you mean about iterators being broken? Or did you mean Enumerations and their lack of concurrent modification checking?
21-04-2016
At the same time, using an iterator on these classes is uterly broken
21-04-2016
I would not deprecate Vector and Hashtable - they are currently the best synchronized List and Map implementations we have. They're in heavy use in the JDK sources.