-
Bug
-
Resolution: Duplicate
-
P4
-
None
-
1.4.1
-
x86
-
linux
Name: gm110360 Date: 10/07/2002
FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
Also:
java version "1.3.1_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_03-b03)
Java HotSpot(TM) Client VM (build 1.3.1_03-b03, mixed mode)
FULL OPERATING SYSTEM VERSION :
Linux 2.4.19-gentoo-r9 running on an AMD XP.
ADDITIONAL OPERATING SYSTEMS :
This is an issue with the code in the standard Java
libraries. I have not checked, but it should be operating
system independent.
A DESCRIPTION OF THE PROBLEM :
ArrayList constructor should assign result of
Collection.toArray(Object[])
I would like to suggest a change to one of ArrayList's
constructors. This improvement would solve a problem for me,
but it would also eliminate a minor race condition.
The change is simple enough that it might be worth making,
despite its limited benefit.
At the moment one of the constructors for ArrayList looks
like this:
public ArrayList(Collection c) {
size = c.size();
// Allow 10% room for growth
elementData = new Object[
(int)Math.min((size*110L)/100,Integer.MAX_VALUE)];
c.toArray(elementData);
}
I think that the last line should be changed to:
elementData = c.toArray(elementData);
Usually, the behaviour of the two pieces of code would be
just the same. However the change would allow it to cope
with two situations. As I mentioned earlier, one is a minor
race condition. The other is more difficult to deal with, is
only likely to affect me.
[Situation 1] The size of the collection changes.
If the Collection's size changes (by over 10%) between the
call to c.size() and the call to c.toArray() then the
changed code will work correctly. The original code will
populate the ArrayList with a truncated version of the
Collection.
This fixes a small problem, but I think it is worth making.
This race condition might not look particularly important,
but an ArrayList is often used (by me, anyway) to take a
'snapshot' of a synchronized List. It would be nice if the
operation was atomic.
[Situation 2] When the Collection is a 'remote' object.
In my application I am wrapping Java's collections so they
can work natively in the Ozone ODB
(http://www.ozone-db.org/). In this application, the
toArray(Object[]) method is sometimes called on a proxy
Collection object.
The proxy Collection operates just like a normal Collection
except it de/serializes the arguments and return values.
This means that using the array as an in/out variable
doesn't work. If I try to construct an ArrayList from a
proxy Collection I just get a List of nulls.
In conclusion, this change would make the code more robust
under unusual conditions. It would impose a small
performance cost (an extra assignment), but I think this is
justified. The real cost is the cost of retesting, which I
can't really comment on.
REPRODUCIBILITY :
This bug can be reproduced always.
CUSTOMER WORKAROUND :
I am describing a flaw in the code rather than its
behaviour, so there is no real workaround. However, there is
a workaround for the examples I use in each the situations I
describe.
[Situation 1] Getting an atomic copy of a synchronized list
Arrays.asList(synchronizedList.toArray())
[Situation 2] Getting a copy of a 'remote' list
Arrays.asList(remoteList.toArray())
(Review ID: 165338)
======================================================================
FULL PRODUCT VERSION :
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1-b21)
Java HotSpot(TM) Client VM (build 1.4.1-b21, mixed mode)
Also:
java version "1.3.1_03"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1_03-b03)
Java HotSpot(TM) Client VM (build 1.3.1_03-b03, mixed mode)
FULL OPERATING SYSTEM VERSION :
Linux 2.4.19-gentoo-r9 running on an AMD XP.
ADDITIONAL OPERATING SYSTEMS :
This is an issue with the code in the standard Java
libraries. I have not checked, but it should be operating
system independent.
A DESCRIPTION OF THE PROBLEM :
ArrayList constructor should assign result of
Collection.toArray(Object[])
I would like to suggest a change to one of ArrayList's
constructors. This improvement would solve a problem for me,
but it would also eliminate a minor race condition.
The change is simple enough that it might be worth making,
despite its limited benefit.
At the moment one of the constructors for ArrayList looks
like this:
public ArrayList(Collection c) {
size = c.size();
// Allow 10% room for growth
elementData = new Object[
(int)Math.min((size*110L)/100,Integer.MAX_VALUE)];
c.toArray(elementData);
}
I think that the last line should be changed to:
elementData = c.toArray(elementData);
Usually, the behaviour of the two pieces of code would be
just the same. However the change would allow it to cope
with two situations. As I mentioned earlier, one is a minor
race condition. The other is more difficult to deal with, is
only likely to affect me.
[Situation 1] The size of the collection changes.
If the Collection's size changes (by over 10%) between the
call to c.size() and the call to c.toArray() then the
changed code will work correctly. The original code will
populate the ArrayList with a truncated version of the
Collection.
This fixes a small problem, but I think it is worth making.
This race condition might not look particularly important,
but an ArrayList is often used (by me, anyway) to take a
'snapshot' of a synchronized List. It would be nice if the
operation was atomic.
[Situation 2] When the Collection is a 'remote' object.
In my application I am wrapping Java's collections so they
can work natively in the Ozone ODB
(http://www.ozone-db.org/). In this application, the
toArray(Object[]) method is sometimes called on a proxy
Collection object.
The proxy Collection operates just like a normal Collection
except it de/serializes the arguments and return values.
This means that using the array as an in/out variable
doesn't work. If I try to construct an ArrayList from a
proxy Collection I just get a List of nulls.
In conclusion, this change would make the code more robust
under unusual conditions. It would impose a small
performance cost (an extra assignment), but I think this is
justified. The real cost is the cost of retesting, which I
can't really comment on.
REPRODUCIBILITY :
This bug can be reproduced always.
CUSTOMER WORKAROUND :
I am describing a flaw in the code rather than its
behaviour, so there is no real workaround. However, there is
a workaround for the examples I use in each the situations I
describe.
[Situation 1] Getting an atomic copy of a synchronized list
Arrays.asList(synchronizedList.toArray())
[Situation 2] Getting a copy of a 'remote' list
Arrays.asList(remoteList.toArray())
(Review ID: 165338)
======================================================================
- duplicates
-
JDK-6347106 (coll) Make ArrayList(Collection) more threadsafe
-
- Closed
-