Forwarding to correct core-libs-dev list.

-Chris.

On 31 Jan 2014, at 14:22, Chris Hegarty <chris.hega...@oracle.com> wrote:

> Hi Robert,
> 
> I think your patch can be split into two logical, independent, parts. The 
> first is the use of unsafe to access the String UTF length. The seconds is to 
> reuse, where possible, the existing StringBuilder instances, skipping of 
> primitive/object reading/writing where applicable, and general cleanup.
> 
> Since this is a very sensitive area I would like to consider these 
> separately. To that end, I have taken the changes that are applicable to the 
> latter, removed any subjective stylistic changes, and made some additional 
> cleanup improvements.
> 
> http://cr.openjdk.java.net/~chegar/serial_stupp.00/webrev/
> 
> Specifically,
> * I think for clarify and readability SerialCallbackContext
>   checkAndSetUsed() should be invoked directly. It makes it very
>   clear what the intent is.
> * Skip primitive/object reading/writing if no primitives/objects in
>   the stream/class. ( I personally don't see any benefit of rounding
>   up the size of the array, it just seems to add unnecessary
>   complexity )
> * Move primitive types into getPrimitiveSignature for better reuse
>   of code. This retains your change to not create the additional
>   StringBuilder when it is not necessary.
> 
> I am currently running tests on this change.
> 
> -Chris.
> 
> On 07/01/14 13:03, Robert Stupp wrote:
>> Hi,
>> I've attached the diff to the original email - it has been stripped.
>> Here's a second try (inline).
>> I've already signed the OCA and it has been approved :)
>> Robert
>> # HG changeset patch
>> # User snazy
>> # Date 1387101091 -3600
>> #      Sun Dec 15 10:51:31 2013 +0100
>> # Node ID 6d46d99212453017c88417678d08dc8f10da9606
>> # Parent  9e1be800420265e5dcf264a7ed4abb6f230dd19d
>> Removed some unnecessary variable assignments.
>> ObjectInputStream:
>> - skip primitive/object reading if no primitive/objects in class
>> - use shared StringBuilder for string reading (prevent superfluous
>> object allocations)
>> ObjectOutputStream:
>> - skip primitive/object writing if no primitive/objects in class
>> - use unsafe access to calculate UTF-length
>> - use unsafe access in readBytes() and writeChars() methods to access
>> String value field
>> - removed cbuf field
>> ObjectStreamClass/ObjectStreamField:
>> - minor improvement in getClassSignature ; share method code with
>> ObjectStreamField
>> diff --git a/src/share/classes/java/io/ObjectInputStream.java
>> b/src/share/classes/java/io/ObjectInputStream.java
>> --- a/src/share/classes/java/io/ObjectInputStream.java
>> +++ b/src/share/classes/java/io/ObjectInputStream.java
>> @@ -39,8 +39,8 @@
>>  import java.util.HashMap;
>>  import java.util.concurrent.ConcurrentHashMap;
>>  import java.util.concurrent.ConcurrentMap;
>> -import java.util.concurrent.atomic.AtomicBoolean;
>>  import static java.io.ObjectStreamClass.processQueue;
>> +
>>  import sun.reflect.misc.ReflectUtil;
>> 
>>  /**
>> @@ -534,7 +534,7 @@
>>          if (ctx == null) {
>>              throw new NotActiveException("not in call to readObject");
>>          }
>> -        Object curObj = ctx.getObj();
>> +        ctx.getObj();
>>          ObjectStreamClass curDesc = ctx.getDesc();
>>          bin.setBlockDataMode(false);
>>          GetFieldImpl getField = new GetFieldImpl(curDesc);
>> @@ -1597,7 +1597,7 @@
>>          int descHandle = handles.assign(unshared ? unsharedMarker : desc);
>>          passHandle = NULL_HANDLE;
>> 
>> -        ObjectStreamClass readDesc = null;
>> +        ObjectStreamClass readDesc;
>>          try {
>>              readDesc = readClassDescriptor();
>>          } catch (ClassNotFoundException ex) {
>> @@ -1976,29 +1976,34 @@
>>          }
>> 
>>          int primDataSize = desc.getPrimDataSize();
>> -        if (primVals == null || primVals.length < primDataSize) {
>> -            primVals = new byte[primDataSize];
>> -        }
>> -        bin.readFully(primVals, 0, primDataSize, false);
>> -        if (obj != null) {
>> -            desc.setPrimFieldValues(obj, primVals);
>> -        }
>> -
>> -        int objHandle = passHandle;
>> -        ObjectStreamField[] fields = desc.getFields(false);
>> -        Object[] objVals = new Object[desc.getNumObjFields()];
>> -        int numPrimFields = fields.length - objVals.length;
>> -        for (int i = 0; i < objVals.length; i++) {
>> -            ObjectStreamField f = fields[numPrimFields + i];
>> -            objVals[i] = readObject0(f.isUnshared());
>> -            if (f.getField() != null) {
>> -                handles.markDependency(objHandle, passHandle);
>> +        if (primDataSize > 0) {
>> +            if (primVals == null || primVals.length < primDataSize) {
>> +                primVals = new byte[ ((primDataSize>>4)+1)<<4 ];
>> +            }
>> +            bin.readFully(primVals, 0, primDataSize, false);
>> +            if (obj != null) {
>> +                desc.setPrimFieldValues(obj, primVals);
>>              }
>>          }
>> -        if (obj != null) {
>> -            desc.setObjFieldValues(obj, objVals);
>> +
>> +        int numObjFields = desc.getNumObjFields();
>> +        if (numObjFields > 0) {
>> +            int objHandle = passHandle;
>> +            ObjectStreamField[] fields = desc.getFields(false);
>> +            Object[] objVals = new Object[numObjFields];
>> +            int numPrimFields = fields.length - objVals.length;
>> +            for (int i = 0; i < objVals.length; i++) {
>> +                ObjectStreamField f = fields[numPrimFields + i];
>> +                objVals[i] = readObject0(f.isUnshared());
>> +                if (f.getField() != null) {
>> +                    handles.markDependency(objHandle, passHandle);
>> +                }
>> +            }
>> +            if (obj != null) {
>> +                desc.setObjFieldValues(obj, objVals);
>> +            }
>> +            passHandle = objHandle;
>>          }
>> -        passHandle = objHandle;
>>      }
>> 
>>      /**
>> @@ -2377,8 +2382,10 @@
>>          private final byte[] buf = new byte[MAX_BLOCK_SIZE];
>>          /** buffer for reading block data headers */
>>          private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
>> -        /** char buffer for fast string reads */
>> +        /** char buffer for fast string reads - used by {@link
>> #readUTFSpan(long)} */
>>          private final char[] cbuf = new char[CHAR_BUF_SIZE];
>> +        /** shared string builder for less object allocations - used by
>> {@link #readUTFBody(long)}, {@link #readUTFChar(long)} and {@link
>> #readUTFSpan(long)} */
>> +        private final StringBuilder sbuf = new
>> StringBuilder(CHAR_BUF_SIZE);
>> 
>>          /** block data mode */
>>          private boolean blkmode = false;
>> @@ -3044,19 +3051,19 @@
>>           * utflen bytes.
>>           */
>>          private String readUTFBody(long utflen) throws IOException {
>> -            StringBuilder sbuf = new StringBuilder();
>>              if (!blkmode) {
>>                  end = pos = 0;
>>              }
>> 
>> +            sbuf.setLength(0);
>>              while (utflen > 0) {
>>                  int avail = end - pos;
>>                  if (avail >= 3 || (long) avail == utflen) {
>> -                    utflen -= readUTFSpan(sbuf, utflen);
>> +                    utflen -= readUTFSpan(utflen);
>>                  } else {
>>                      if (blkmode) {
>>                          // near block boundary, read one byte at a time
>> -                        utflen -= readUTFChar(sbuf, utflen);
>> +                        utflen -= readUTFChar(utflen);
>>                      } else {
>>                          // shift and refill buffer manually
>>                          if (avail > 0) {
>> @@ -3076,10 +3083,10 @@
>>           * Reads span of UTF-encoded characters out of internal buffer
>>           * (starting at offset pos and ending at or before offset end),
>>           * consuming no more than utflen bytes.  Appends read
>> characters to
>> -         * sbuf.  Returns the number of bytes consumed.
>> +         * {@link #sbuf}.  Returns the number of bytes consumed.
>>           */
>> -        private long readUTFSpan(StringBuilder sbuf, long utflen)
>> -            throws IOException
>> +        private long readUTFSpan(long utflen)
>> +                throws IOException
>>          {
>>              int cpos = 0;
>>              int start = pos;
>> @@ -3111,19 +3118,19 @@
>>                                  throw new UTFDataFormatException();
>>                              }
>>                              cbuf[cpos++] = (char) (((b1 & 0x1F) << 6) |
>> -                                                   ((b2 & 0x3F) << 0));
>> +                                    (b2 & 0x3F));
>>                              break;
>> 
>>                          case 14:  // 3 byte format: 1110xxxx 10xxxxxx
>> 10xxxxxx
>>                              b3 = buf[pos + 1];
>> -                            b2 = buf[pos + 0];
>> +                            b2 = buf[pos    ];
>>                              pos += 2;
>>                              if ((b2 & 0xC0) != 0x80 || (b3 & 0xC0) !=
>> 0x80) {
>>                                  throw new UTFDataFormatException();
>>                              }
>>                              cbuf[cpos++] = (char) (((b1 & 0x0F) << 12) |
>> -                                                   ((b2 & 0x3F) << 6) |
>> -                                                   ((b3 & 0x3F) << 0));
>> +                                    ((b2 & 0x3F) << 6) |
>> +                                    (b3 & 0x3F));
>>                              break;
>> 
>>                          default:  // 10xx xxxx, 1111 xxxx
>> @@ -3150,12 +3157,12 @@
>> 
>>          /**
>>           * Reads in single UTF-encoded character one byte at a time,
>> appends
>> -         * the character to sbuf, and returns the number of bytes consumed.
>> +         * the character to {@link #sbuf}, and returns the number of
>> bytes consumed.
>>           * This method is used when reading in UTF strings written in
>> block
>>           * data mode to handle UTF-encoded characters which (potentially)
>>           * straddle block-data boundaries.
>>           */
>> -        private int readUTFChar(StringBuilder sbuf, long utflen)
>> +        private int readUTFChar(long utflen)
>>              throws IOException
>>          {
>>              int b1, b2, b3;
>> @@ -3181,8 +3188,7 @@
>>                      if ((b2 & 0xC0) != 0x80) {
>>                          throw new UTFDataFormatException();
>>                      }
>> -                    sbuf.append((char) (((b1 & 0x1F) << 6) |
>> -                                        ((b2 & 0x3F) << 0)));
>> +                    sbuf.append((char) (((b1 & 0x1F) << 6) | (b2 & 0x3F)));
>>                      return 2;
>> 
>>                  case 14:    // 3 byte format: 1110xxxx 10xxxxxx 10xxxxxx
>> @@ -3198,8 +3204,8 @@
>>                          throw new UTFDataFormatException();
>>                      }
>>                      sbuf.append((char) (((b1 & 0x0F) << 12) |
>> -                                        ((b2 & 0x3F) << 6) |
>> -                                        ((b3 & 0x3F) << 0)));
>> +                            ((b2 & 0x3F) << 6) |
>> +                            (b3 & 0x3F)));
>>                      return 3;
>> 
>>                  default:   // 10xx xxxx, 1111 xxxx
>> diff --git a/src/share/classes/java/io/ObjectOutputStream.java
>> b/src/share/classes/java/io/ObjectOutputStream.java
>> --- a/src/share/classes/java/io/ObjectOutputStream.java
>> +++ b/src/share/classes/java/io/ObjectOutputStream.java
>> @@ -35,7 +35,8 @@
>>  import java.util.concurrent.ConcurrentHashMap;
>>  import java.util.concurrent.ConcurrentMap;
>>  import static java.io.ObjectStreamClass.processQueue;
>> -import java.io.SerialCallbackContext;
>> +
>> +import sun.misc.Unsafe;
>>  import sun.reflect.misc.ReflectUtil;
>> 
>>  /**
>> @@ -458,7 +459,7 @@
>>              if (ctx == null) {
>>                  throw new NotActiveException("not in call to
>> writeObject");
>>              }
>> -            Object curObj = ctx.getObj();
>> +            ctx.getObj();
>>              ObjectStreamClass curDesc = ctx.getDesc();
>>              curPut = new PutFieldImpl(curDesc);
>>          }
>> @@ -1300,7 +1301,7 @@
>>       */
>>      private void writeString(String str, boolean unshared) throws
>> IOException {
>>          handles.assign(unshared ? null : str);
>> -        long utflen = bout.getUTFLength(str);
>> +        long utflen = BlockDataOutputStream.getUTFLength(str);
>>          if (utflen <= 0xFFFF) {
>>              bout.writeByte(TC_STRING);
>>              bout.writeUTF(str, utflen);
>> @@ -1527,29 +1528,34 @@
>>          desc.checkDefaultSerialize();
>> 
>>          int primDataSize = desc.getPrimDataSize();
>> -        if (primVals == null || primVals.length < primDataSize) {
>> -            primVals = new byte[primDataSize];
>> +        if (primDataSize > 0) {
>> +            if (primVals == null || primVals.length < primDataSize) {
>> +                primVals = new byte[ ((primDataSize>>4)+1)<<4 ];
>> +            }
>> +            desc.getPrimFieldValues(obj, primVals);
>> +            bout.write(primVals, 0, primDataSize, false);
>>          }
>> -        desc.getPrimFieldValues(obj, primVals);
>> -        bout.write(primVals, 0, primDataSize, false);
>> 
>> -        ObjectStreamField[] fields = desc.getFields(false);
>> -        Object[] objVals = new Object[desc.getNumObjFields()];
>> -        int numPrimFields = fields.length - objVals.length;
>> -        desc.getObjFieldValues(obj, objVals);
>> -        for (int i = 0; i < objVals.length; i++) {
>> -            if (extendedDebugInfo) {
>> -                debugInfoStack.push(
>> -                    "field (class \"" + desc.getName() + "\", name: \"" +
>> -                    fields[numPrimFields + i].getName() + "\", type: \"" +
>> -                    fields[numPrimFields + i].getType() + "\")");
>> -            }
>> -            try {
>> -                writeObject0(objVals[i],
>> -                             fields[numPrimFields + i].isUnshared());
>> -            } finally {
>> +        int numObjFields = desc.getNumObjFields();
>> +        if (numObjFields > 0) {
>> +            ObjectStreamField[] fields = desc.getFields(false);
>> +            Object[] objVals = new Object[numObjFields];
>> +            int numPrimFields = fields.length - objVals.length;
>> +            desc.getObjFieldValues(obj, objVals);
>> +            for (int i = 0; i < objVals.length; i++) {
>>                  if (extendedDebugInfo) {
>> -                    debugInfoStack.pop();
>> +                    debugInfoStack.push(
>> +                        "field (class \"" + desc.getName() + "\", name:
>> \"" +
>> +                        fields[numPrimFields + i].getName() + "\",
>> type: \"" +
>> +                        fields[numPrimFields + i].getType() + "\")");
>> +                }
>> +                try {
>> +                    writeObject0(objVals[i],
>> +                                 fields[numPrimFields + i].isUnshared());
>> +                } finally {
>> +                    if (extendedDebugInfo) {
>> +                        debugInfoStack.pop();
>> +                    }
>>                  }
>>              }
>>          }
>> @@ -1743,15 +1749,11 @@
>>          private static final int MAX_BLOCK_SIZE = 1024;
>>          /** maximum data block header length */
>>          private static final int MAX_HEADER_SIZE = 5;
>> -        /** (tunable) length of char buffer (for writing strings) */
>> -        private static final int CHAR_BUF_SIZE = 256;
>> 
>>          /** buffer for writing general/block data */
>>          private final byte[] buf = new byte[MAX_BLOCK_SIZE];
>>          /** buffer for writing block data headers */
>>          private final byte[] hbuf = new byte[MAX_HEADER_SIZE];
>> -        /** char buffer for fast string writes */
>> -        private final char[] cbuf = new char[CHAR_BUF_SIZE];
>> 
>>          /** block data mode */
>>          private boolean blkmode = false;
>> @@ -1763,6 +1765,18 @@
>>          /** loopback stream (for data writes that span data blocks) */
>>          private final DataOutputStream dout;
>> 
>> +        /** use unsafe to directly access value field in
>> java.lang.String */
>> +        private static final Unsafe unsafe = Unsafe.getUnsafe();
>> +        /** use field offset to directly access value field in
>> java.lang.String */
>> +        private static final long stringValueOffset;
>> +        static {
>> +            try {
>> +                stringValueOffset =
>> unsafe.objectFieldOffset(String.class.getDeclaredField("value"));
>> +            } catch (NoSuchFieldException e) {
>> +                throw new InternalError(e);
>> +            }
>> +        }
>> +
>>          /**
>>           * Creates new BlockDataOutputStream on top of given
>> underlying stream.
>>           * Block data mode is turned off by default.
>> @@ -1972,35 +1986,23 @@
>>          }
>> 
>>          public void writeBytes(String s) throws IOException {
>> -            int endoff = s.length();
>> -            int cpos = 0;
>> -            int csize = 0;
>> +            char[] sChars = (char[])unsafe.getObject(s, stringValueOffset);
>> +            int endoff = sChars.length;
>>              for (int off = 0; off < endoff; ) {
>> -                if (cpos >= csize) {
>> -                    cpos = 0;
>> -                    csize = Math.min(endoff - off, CHAR_BUF_SIZE);
>> -                    s.getChars(off, off + csize, cbuf, 0);
>> -                }
>>                  if (pos >= MAX_BLOCK_SIZE) {
>>                      drain();
>>                  }
>> -                int n = Math.min(csize - cpos, MAX_BLOCK_SIZE - pos);
>> +                int n = Math.min(endoff - off, MAX_BLOCK_SIZE - pos);
>>                  int stop = pos + n;
>>                  while (pos < stop) {
>> -                    buf[pos++] = (byte) cbuf[cpos++];
>> +                    buf[pos++] = (byte) sChars[off++];
>>                  }
>> -                off += n;
>>              }
>>          }
>> 
>>          public void writeChars(String s) throws IOException {
>> -            int endoff = s.length();
>> -            for (int off = 0; off < endoff; ) {
>> -                int csize = Math.min(endoff - off, CHAR_BUF_SIZE);
>> -                s.getChars(off, off + csize, cbuf, 0);
>> -                writeChars(cbuf, 0, csize);
>> -                off += csize;
>> -            }
>> +            char[] sChars = (char[])unsafe.getObject(s, stringValueOffset);
>> +            writeChars(sChars, 0, sChars.length);
>>          }
>> 
>>          public void writeUTF(String s) throws IOException {
>> @@ -2130,25 +2132,21 @@
>>          }
>> 
>>          /**
>> -         * Returns the length in bytes of the UTF encoding of the given
>> string.
>> +         * Returns the length in bytes of the UTF encoding of this
>> given string.
>>           */
>> -        long getUTFLength(String s) {
>> -            int len = s.length();
>> +        static long getUTFLength(String s) {
>> +            char[] value = (char[])unsafe.getObject(s, stringValueOffset);
>> +            int len = value.length;
>>              long utflen = 0;
>>              for (int off = 0; off < len; ) {
>> -                int csize = Math.min(len - off, CHAR_BUF_SIZE);
>> -                s.getChars(off, off + csize, cbuf, 0);
>> -                for (int cpos = 0; cpos < csize; cpos++) {
>> -                    char c = cbuf[cpos];
>> -                    if (c >= 0x0001 && c <= 0x007F) {
>> -                        utflen++;
>> -                    } else if (c > 0x07FF) {
>> -                        utflen += 3;
>> -                    } else {
>> -                        utflen += 2;
>> -                    }
>> +                char c = value[off++];
>> +                if (c >= 0x0001 && c <= 0x007F) {
>> +                    utflen++;
>> +                } else if (c > 0x07FF) {
>> +                    utflen += 3;
>> +                } else {
>> +                    utflen += 2;
>>                  }
>> -                off += csize;
>>              }
>>              return utflen;
>>          }
>> @@ -2198,40 +2196,36 @@
>>           * 8-byte length header) of the UTF encoding for the given string.
>>           */
>>          private void writeUTFBody(String s) throws IOException {
>> +            char[] sChars = (char[])unsafe.getObject(s, stringValueOffset);
>> +            int len = sChars.length;
>>              int limit = MAX_BLOCK_SIZE - 3;
>> -            int len = s.length();
>>              for (int off = 0; off < len; ) {
>> -                int csize = Math.min(len - off, CHAR_BUF_SIZE);
>> -                s.getChars(off, off + csize, cbuf, 0);
>> -                for (int cpos = 0; cpos < csize; cpos++) {
>> -                    char c = cbuf[cpos];
>> -                    if (pos <= limit) {
>> -                        if (c <= 0x007F && c != 0) {
>> -                            buf[pos++] = (byte) c;
>> -                        } else if (c > 0x07FF) {
>> -                            buf[pos + 2] = (byte) (0x80 | ((c >> 0) &
>> 0x3F));
>> -                            buf[pos + 1] = (byte) (0x80 | ((c >> 6) &
>> 0x3F));
>> -                            buf[pos + 0] = (byte) (0xE0 | ((c >> 12) &
>> 0x0F));
>> -                            pos += 3;
>> -                        } else {
>> -                            buf[pos + 1] = (byte) (0x80 | ((c >> 0) &
>> 0x3F));
>> -                            buf[pos + 0] = (byte) (0xC0 | ((c >> 6) &
>> 0x1F));
>> -                            pos += 2;
>> -                        }
>> -                    } else {    // write one byte at a time to
>> normalize block
>> -                        if (c <= 0x007F && c != 0) {
>> -                            write(c);
>> -                        } else if (c > 0x07FF) {
>> -                            write(0xE0 | ((c >> 12) & 0x0F));
>> -                            write(0x80 | ((c >> 6) & 0x3F));
>> -                            write(0x80 | ((c >> 0) & 0x3F));
>> -                        } else {
>> -                            write(0xC0 | ((c >> 6) & 0x1F));
>> -                            write(0x80 | ((c >> 0) & 0x3F));
>> -                        }
>> +                char c = sChars[off++];
>> +                if (pos <= limit) {
>> +                    if (c <= 0x007F && c != 0) {
>> +                        buf[pos++] = (byte) c;
>> +                    } else if (c > 0x07FF) {
>> +                        buf[pos + 2] = (byte) (0x80 | ( c       & 0x3F));
>> +                        buf[pos + 1] = (byte) (0x80 | ((c >> 6) & 0x3F));
>> +                        buf[pos    ] = (byte) (0xE0 | ((c >> 12) & 0x0F));
>> +                        pos += 3;
>> +                    } else {
>> +                        buf[pos + 1] = (byte) (0x80 | ( c       & 0x3F));
>> +                        buf[pos    ] = (byte) (0xC0 | ((c >> 6) & 0x1F));
>> +                        pos += 2;
>> +                    }
>> +                } else {    // write one byte at a time to normalize block
>> +                    if (c <= 0x007F && c != 0) {
>> +                        write(c);
>> +                    } else if (c > 0x07FF) {
>> +                        write(0xE0 | ((c >> 12) & 0x0F));
>> +                        write(0x80 | ((c >> 6) & 0x3F));
>> +                        write(0x80 | ( c       & 0x3F));
>> +                    } else {
>> +                        write(0xC0 | ((c >> 6) & 0x1F));
>> +                        write(0x80 | ( c       & 0x3F));
>>                      }
>>                  }
>> -                off += csize;
>>              }
>>          }
>>      }
>> @@ -2464,7 +2458,10 @@
>>              StringBuilder buffer = new StringBuilder();
>>              if (!stack.isEmpty()) {
>>                  for(int i = stack.size(); i > 0; i-- ) {
>> -                    buffer.append(stack.get(i-1) + ((i != 1) ? "\n" : ""));
>> +                    buffer.append(stack.get(i - 1));
>> +                    if (i!=1) {
>> +                        buffer.append('\n');
>> +                    }
>>                  }
>>              }
>>              return buffer.toString();
>> diff --git a/src/share/classes/java/io/ObjectStreamClass.java
>> b/src/share/classes/java/io/ObjectStreamClass.java
>> --- a/src/share/classes/java/io/ObjectStreamClass.java
>> +++ b/src/share/classes/java/io/ObjectStreamClass.java
>> @@ -1474,7 +1474,28 @@
>>      /**
>>       * Returns JVM type signature for given class.
>>       */
>> -    private static String getClassSignature(Class<?> cl) {
>> +    static String getClassSignature(Class<?> cl) {
>> +        if (cl.isPrimitive())
>> +            if (cl == Integer.TYPE) {
>> +                return "I";
>> +            } else if (cl == Byte.TYPE) {
>> +                return "B";
>> +            } else if (cl == Long.TYPE) {
>> +                return "J";
>> +            } else if (cl == Float.TYPE) {
>> +                return "F";
>> +            } else if (cl == Double.TYPE) {
>> +                return "D";
>> +            } else if (cl == Short.TYPE) {
>> +                return "S";
>> +            } else if (cl == Character.TYPE) {
>> +                return "C";
>> +            } else if (cl == Boolean.TYPE) {
>> +                return "Z";
>> +            } else if (cl == Void.TYPE) {
>> +                return "V";
>> +            }
>> +
>>          StringBuilder sbuf = new StringBuilder();
>>          while (cl.isArray()) {
>>              sbuf.append('[');
>> @@ -1503,7 +1524,7 @@
>>                  throw new InternalError();
>>              }
>>          } else {
>> -            sbuf.append('L' + cl.getName().replace('.', '/') + ';');
>> +            sbuf.append('L').append(cl.getName().replace('.',
>> '/')).append(';');
>>          }
>>          return sbuf.toString();
>>      }
>> diff --git a/src/share/classes/java/io/ObjectStreamField.java
>> b/src/share/classes/java/io/ObjectStreamField.java
>> --- a/src/share/classes/java/io/ObjectStreamField.java
>> +++ b/src/share/classes/java/io/ObjectStreamField.java
>> @@ -91,7 +91,7 @@
>>          this.name = name;
>>          this.type = type;
>>          this.unshared = unshared;
>> -        signature = getClassSignature(type).intern();
>> +        signature = ObjectStreamClass.getClassSignature(type).intern();
>>          field = null;
>>      }
>> 
>> @@ -137,7 +137,7 @@
>>          name = field.getName();
>>          Class<?> ftype = field.getType();
>>          type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
>> -        signature = getClassSignature(ftype).intern();
>> +        signature = ObjectStreamClass.getClassSignature(ftype).intern();
>>      }
>> 
>>      /**
>> @@ -286,41 +286,4 @@
>>      String getSignature() {
>>          return signature;
>>      }
>> -
>> -    /**
>> -     * Returns JVM type signature for given class.
>> -     */
>> -    private static String getClassSignature(Class<?> cl) {
>> -        StringBuilder sbuf = new StringBuilder();
>> -        while (cl.isArray()) {
>> -            sbuf.append('[');
>> -            cl = cl.getComponentType();
>> -        }
>> -        if (cl.isPrimitive()) {
>> -            if (cl == Integer.TYPE) {
>> -                sbuf.append('I');
>> -            } else if (cl == Byte.TYPE) {
>> -                sbuf.append('B');
>> -            } else if (cl == Long.TYPE) {
>> -                sbuf.append('J');
>> -            } else if (cl == Float.TYPE) {
>> -                sbuf.append('F');
>> -            } else if (cl == Double.TYPE) {
>> -                sbuf.append('D');
>> -            } else if (cl == Short.TYPE) {
>> -                sbuf.append('S');
>> -            } else if (cl == Character.TYPE) {
>> -                sbuf.append('C');
>> -            } else if (cl == Boolean.TYPE) {
>> -                sbuf.append('Z');
>> -            } else if (cl == Void.TYPE) {
>> -                sbuf.append('V');
>> -            } else {
>> -                throw new InternalError();
>> -            }
>> -        } else {
>> -            sbuf.append('L' + cl.getName().replace('.', '/') + ';');
>> -        }
>> -        return sbuf.toString();
>> -    }
>>  }
>> *Gesendet:* Dienstag, 07. Januar 2014 um 10:05 Uhr
>> *Von:* "Chris Hegarty" <chris.hega...@oracle.com>
>> *An:* "Robert Stupp" <sn...@gmx.de>
>> *Cc:* "core-libs-dev@openjdk.java.net Libs" <core-libs-dev@openjdk.java.net>
>> *Betreff:* Re: ObjectIn/OutputStream improvements
>> On 15 Dec 2013, at 10:29, Robert Stupp <sn...@gmx.de> wrote:
>> 
>> > Hi,
>> >
>> > I digged through the object serialization code and found some lines
>> that could be optimized to reduce the number of calls to
>> System.arraycopy() and temporary object allocations especially during
>> string (de)serialization.
>> > In short sentences the changes are:
>> > ObjectInputStream:
>> > - skip primitive/object reading if no primitive/objects in class
>> (defaultReadFields method)
>> > - use shared StringBuilder for string reading (prevent superfluous
>> object allocations of one StingBuilder and one implicit char[] for each
>> string being deserialized)
>> > ObjectOutputStream:
>> > - skip primitive/object writing if no primitive/objects in class
>> (defaultWriteFields method)
>> > - use unsafe access to calculate UTF-length
>> > - use unsafe access in readBytes() and writeChars() methods to access
>> String value field
>> > - removed cbuf field
>> > ObjectStreamClass/ObjectStreamField:
>> > - minor improvement in getClassSignature ; share method code with
>> ObjectStreamField (return constant string for primitives)
>> >
>> > I have tested the changes in a big Java installation at a customer
>> (backported the Java8 ObjectIn/OutputStream including the changes to
>> Java6) and a long running real application performance test resulted in
>> reduced CPU usage (from about 60% per server to 50%).
>> > The changes I made in openjdk8 pass all tests.
>> >
>> > Since I have no experience how to contribute code to openjdk in form
>> of a push/changeset I have added the diff (hg export -g) to this email.
>> 
>> Did you attach the diffs? I don’t see any attachment, it may be that the
>> attachment was stripped. Can you try resending inline?
>> 
>> You should take a look at the OpenJDK How to Contribute page [1]. Paying
>> particular attention to the OCA, without it we will not be able to move
>> your patch forward.
>> 
>> Thanks,
>> -Chris.
>> 
>> [1] http://openjdk.java.net/contribute/
>> 
>> >
>> > Robert
>> >
>> >

Reply via email to