JDK-4684279 : Collections.EMPTY_* can be duplicated in system with serialization
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.util
  • Affected Version: 1.4.0
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2002-05-13
  • Updated: 2002-11-27
  • Resolved: 2002-11-20
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.

To download the current JDK release, click here.
Other
1.4.2 mantisFixed
Description

Name: nt126004			Date: 05/13/2002


FULL PRODUCT VERSION :
java version "1.4.0"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.0-b92)
Java HotSpot(TM) Client VM (build 1.4.0-b92, mixed mode)

FULL OPERATING SYSTEM VERSION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
When I serialize Collections.EMPTY_LIST and then deserialize
it, I get a different object.  The two objects are equal via
the equals method, however == doesn't consider them equal.
Since the EMPTY_* variables are defined constants I would
think that deserializing the objects would return the exact
same reference.  This can be accomplised by overriding the
readResolve method in the Empty* class implementations.
Then checking for equality would be quicker.

This bug can be reproduced always.

---------- BEGIN SOURCE ----------
package foo.bugs.jdk;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.IOException;


public class SerializeEmptyCollections {
  
  static public void main(final String[] args) {
    try {
    final ByteArrayOutputStream baos = new ByteArrayOutputStream();
    final ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(Collections.EMPTY_LIST);
    oos.writeObject(Collections.EMPTY_SET);
    oos.writeObject(Collections.EMPTY_MAP);
    oos.close();

    final ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
    final ObjectInputStream ois = new ObjectInputStream(bais);
    final List emptyList = (List)ois.readObject();
    final Set emptySet = (Set)ois.readObject();
    final Map emptyMap = (Map)ois.readObject();
    ois.close();

    System.out.println("empty list == " + (Collections.EMPTY_LIST == emptyList));
    System.out.println("empty list equals " +
(Collections.EMPTY_LIST.equals(emptyList)));

    System.out.println("empty set == " + (Collections.EMPTY_SET == emptySet));
    System.out.println("empty set equals " +
(Collections.EMPTY_SET.equals(emptySet)));

    System.out.println("empty map == " + (Collections.EMPTY_MAP == emptyMap));
    System.out.println("empty map equals " +
(Collections.EMPTY_MAP.equals(emptyMap)));

    } catch(final IOException ioe) {
      ioe.printStackTrace();
    } catch(final ClassNotFoundException cnfe) {
      cnfe.printStackTrace();
    }
  }
}

---------- END SOURCE ----------

CUSTOMER WORKAROUND :
Use equals to compare these lists, rather than ==.
(Review ID: 146455) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: mantis FIXED IN: mantis INTEGRATED IN: mantis mantis-b08 VERIFIED IN: mantis-beta
2004-06-14

EVALUATION In the absence of a specific notation in the spec, it would be reckless to write code that depends on the identity of a deserialized value. That said, this is a reasonable request from a performance and cleanliness perspective. ###@###.### 2002-05-13
2002-05-13