Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8254224

Change DataOutputStream to use its internal buffer for ints, chars, and shorts

    XMLWordPrintable

Details

    • CSR
    • Resolution: Approved
    • P3
    • 16
    • core-libs
    • None
    • behavioral
    • low
    • Hide
      DataOutputStream dates from JDK 1.0. Some methods are synchronized but most methods are not thread safe. It's possible that there is code that depends on the (unspecified) synchronization in the methods that are synchronized but overall the compatibility risk should be low.
      Show
      DataOutputStream dates from JDK 1.0. Some methods are synchronized but most methods are not thread safe. It's possible that there is code that depends on the (unspecified) synchronization in the methods that are synchronized but overall the compatibility risk should be low.
    • Java API
    • SE

    Description

      Summary

      Rewrite the writeXXX methods defined by java.io.DataOutputStream to its internal writeBuffer for temporary storage. This avoids excessive synchronization. Add text to the class description of both java.io.DataOutputStream and java.io.DataInputStream to make it clear that they are not safe for concurrent threads without appropriate synchronization.

      Problem

      Some Stream classes use very fine-grained locking.

      In particular, writeInt is defined like this:

              out.write((v >>> 24) & 0xFF);
              out.write((v >>> 16) & 0xFF);
              out.write((v >>> 8) & 0xFF);
              out.write((v >>> 0) & 0xFF);
              incCount(4);

      Unfortunately, ByteArrayOutputStream.write(byte) is synchronized:

          public synchronized void write(int b) {
            ...
          }

      leading to a monitor being acquired and released for every byte.

      Solution

      DataOutputStream already has an internal byte[] that it uses for temporary storage while outputting longs and doubles. We should use this buffer for ints, chars, and shorts too. Like so:

          public final void writeInt(int v) throws IOException {
              writeBuffer[0] = (byte)(v >>> 24);
              writeBuffer[1] = (byte)(v >>> 16);
              writeBuffer[2] = (byte)(v >>>  8);
              writeBuffer[3] = (byte)(v >>>  0);
              out.write(writeBuffer, 0, 4);
              incCount(4);
          }

      Note that writeDouble() and writeLong() already do exactly this.

      Specification

      There is no specification issue as such: DataOutputStream is not specified to be thread safe. However, if an application writer assumed from the current implementation that racy access to a DataOutputStream was thread safe, it will no longer be. This is because each instance of DataOutputStream uses an internal buffer.

      However, to make the situation clear I have added language to warn users of DataOutputStream that it is not thread safe. I have also modified the language used in DataInputStream to make it less ambiguous.

      Attachments

        1. 8254224.diff
          2 kB
        2. 8254224.diff
          2 kB
        3. 8254224.diff
          2 kB

        Issue Links

          Activity

            People

              aph Andrew Haley
              aph Andrew Haley
              Alan Bateman
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: