harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From apetre...@apache.org
Subject svn commit: r534747 - in /harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io: DataInputStream.java DataOutputStream.java ObjectInputStream.java ObjectOutputStream.java ObjectStreamClass.java
Date Thu, 03 May 2007 07:57:00 GMT
Author: apetrenko
Date: Thu May  3 00:56:58 2007
New Revision: 534747

URL: http://svn.apache.org/viewvc?view=rev&rev=534747
Log:
Patch for HARMONY-3795 "[classlib][linu] Performance improvement for java.io.DataInputStream,
java.io.DataOutputStream, java.io.ObjectInputStream, java.io.ObjectOutputStream and java.io.ObjectStreamClass."

Modified:
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataInputStream.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataOutputStream.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectInputStream.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectOutputStream.java
    harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectStreamClass.java

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataInputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataInputStream.java?view=diff&rev=534747&r1=534746&r2=534747
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataInputStream.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataInputStream.java
Thu May  3 00:56:58 2007
@@ -41,8 +41,12 @@
      * @see DataOutputStream
      * @see RandomAccessFile
      */
+
+    byte[] buff;
+
     public DataInputStream(InputStream in) {
         super(in);
+        buff = new byte[8];
     }
 
     /**
@@ -136,13 +140,23 @@
      * 
      * @see DataOutput#writeChar(int)
      */
+    private int readToBuff(int count) throws IOException {
+        int offset = 0;
+
+        while(offset < count) {
+            int bytesRead = in.read(buff, offset, count - offset);
+            if(bytesRead == -1) return bytesRead;
+            offset += bytesRead;
+        } 
+        return offset;
+    }
+
     public final char readChar() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return (char) ((b1 << 8) + b2);
+        return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
+
     }
 
     /**
@@ -248,14 +262,11 @@
      * @see DataOutput#writeInt(int)
      */
     public final int readInt() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        int b3 = in.read();
-        int b4 = in.read();
-        if ((b1 | b2 | b3 | b4) < 0) {
+        if (readToBuff(4) < 0){
             throw new EOFException();
         }
-        return ((b1 << 24) + (b2 << 16) + (b3 << 8) + b4);
+        return ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16) |
+            ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
     }
 
     /**
@@ -320,16 +331,15 @@
      * @see DataOutput#writeLong(long)
      */
     public final long readLong() throws IOException {
-        int i1 = readInt();
-        int b1 = in.read();
-        int b2 = in.read();
-        int b3 = in.read();
-        int b4 = in.read();
-        if ((b1 | b2 | b3 | b4) < 0) {
+        if (readToBuff(8) < 0){
             throw new EOFException();
         }
-        return (((long) i1) << 32) + ((long) b1 << 24) + (b2 << 16) + (b3
<< 8)
-                + b4;
+        int i1 = ((buff[0] & 0xff) << 24) | ((buff[1] & 0xff) << 16)
|
+            ((buff[2] & 0xff) << 8) | (buff[3] & 0xff);
+        int i2 = ((buff[4] & 0xff) << 24) | ((buff[5] & 0xff) << 16)
|
+            ((buff[6] & 0xff) << 8) | (buff[7] & 0xff);
+
+        return ((i1 & 0xffffffffL) << 32) | (i2 & 0xffffffffL);
     }
 
     /**
@@ -343,12 +353,10 @@
      * @see DataOutput#writeShort(int)
      */
     public final short readShort() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return (short) ((b1 << 8) + b2);
+        return (short) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
     }
 
     /**
@@ -383,12 +391,10 @@
      * @see DataOutput#writeShort(int)
      */
     public final int readUnsignedShort() throws IOException {
-        int b1 = in.read();
-        int b2 = in.read();
-        if ((b1 | b2) < 0) {
+        if (readToBuff(2) < 0){
             throw new EOFException();
         }
-        return ((b1 << 8) + b2);
+        return (char) (((buff[0] & 0xff) << 8) | (buff[1] & 0xff));
     }
 
     /**
@@ -402,72 +408,17 @@
      * @see DataOutput#writeUTF(java.lang.String)
      */
     public final String readUTF() throws IOException {
-        int utfSize = readUnsignedShort();
-        return decodeUTF(utfSize);
-    }
-
-    static final int MAX_BUF_SIZE = 8192;
-
-    private static class CacheLock {
+        return decodeUTF(readUnsignedShort());
     }
 
-    static final Object cacheLock = new CacheLock();
-
-    static boolean useShared = true;
-
-    static byte[] byteBuf = new byte[0];
-
-    static char[] charBuf = new char[0];
 
     String decodeUTF(int utfSize) throws IOException {
-        byte[] buf;
-        char[] out = null;
-        boolean makeBuf = true;
-
-        /*
-         * Try to avoid the synchronization -- if we get a stale value for
-         * useShared then there is no foul below, but those that sync on the
-         * lock must see the right value.
-         */
-        if (utfSize <= MAX_BUF_SIZE && useShared) {
-            synchronized (cacheLock) {
-                if (useShared) {
-                    useShared = false;
-                    makeBuf = false;
-                }
-            }
-        }
-        if (makeBuf) {
-            buf = new byte[utfSize];
-            out = new char[utfSize];
-        } else {
-            /*
-             * Need to 'sample' byteBuf and charBuf before using them because
-             * they are not protected by the cacheLock. They may get out of sync
-             * with the static and one another, but that is ok because we
-             * explicitly check and fix their length after sampling.
-             */
-            buf = byteBuf;
-            if (buf.length < utfSize) {
-                buf = byteBuf = new byte[utfSize];
-            }
-            out = charBuf;
-            if (out.length < utfSize) {
-                out = charBuf = new char[utfSize];
-            }
-        }
 
+        byte[] buf = new byte[utfSize];
+        char[] out = new char[utfSize];
         readFully(buf, 0, utfSize);
-        String result;
-        result = Util.convertUTF8WithBuf(buf, out, 0, utfSize);
-        if (!makeBuf) {
-            /*
-             * Do not synchronize useShared on cacheLock, it will make it back
-             * to main storage at some point, and no harm until it does.
-             */
-            useShared = true;
-        }
-        return result;
+
+        return Util.convertUTF8WithBuf(buf, out, 0, utfSize);
     }
 
     /**

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataOutputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataOutputStream.java?view=diff&rev=534747&r1=534746&r2=534747
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataOutputStream.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/DataOutputStream.java
Thu May  3 00:56:58 2007
@@ -31,6 +31,7 @@
 
     /** The number of bytes written out so far */
     protected int written;
+    byte buff[];
 
     /**
      * Constructs a new DataOutputStream on the OutputStream <code>out</code>.
@@ -43,6 +44,7 @@
      */
     public DataOutputStream(OutputStream out) {
         super(out);
+        buff = new byte[8];
     }
 
     /**
@@ -190,9 +192,9 @@
      * @see DataInput#readChar()
      */
     public final void writeChar(int val) throws IOException {
-        out.write(val >> 8);
-        out.write(val);
-        written += 2;
+        buff[0] = (byte) (val >> 8);
+        buff[1] = (byte) val;
+        out.write(buff, 0, 2);
     }
 
     /**
@@ -269,11 +271,11 @@
      * @see DataInput#readInt()
      */
     public final void writeInt(int val) throws IOException {
-        out.write(val >> 24);
-        out.write(val >> 16);
-        out.write(val >> 8);
-        out.write(val);
-        written += 4;
+        buff[0] = (byte) (val >> 24);
+        buff[1] = (byte) (val >> 16);
+        buff[2] = (byte) (val >> 8);
+        buff[3] = (byte) val;
+        out.write(buff, 0, 4);
     }
 
     /**
@@ -290,8 +292,15 @@
      * @see DataInput#readLong()
      */
     public final void writeLong(long val) throws IOException {
-        writeInt((int) (val >> 32));
-        writeInt((int) val);
+        buff[0] = (byte) (val >> 56);
+        buff[1] = (byte) (val >> 48);
+        buff[2] = (byte) (val >> 40);
+        buff[3] = (byte) (val >> 32);
+        buff[4] = (byte) (val >> 24);
+        buff[5] = (byte) (val >> 16);
+        buff[6] = (byte) (val >> 8);
+        buff[7] = (byte) val;
+        out.write(buff, 0, 8);
     }
 
     /**
@@ -309,7 +318,9 @@
      * @see DataInput#readUnsignedShort()
      */
     public final void writeShort(int val) throws IOException {
-        writeChar(val);
+        buff[0] = (byte) (val >> 8);
+        buff[1] = (byte) val;
+        out.write(buff, 0, 2);
     }
 
     /**
@@ -325,53 +336,12 @@
      * @see DataInput#readUTF()
      */
     public final void writeUTF(String str) throws IOException {
-        int length = str.length();
-        if (length <= DataInputStream.MAX_BUF_SIZE / 3) {
-            int size = length * 3;
-            byte[] utfBytes;
-            boolean makeBuf = true;
-            synchronized (DataInputStream.byteBuf) {
-                if (DataInputStream.useShared) {
-                    DataInputStream.useShared = false;
-                    makeBuf = false;
-                }
-            }
-            if (makeBuf) {
-                utfBytes = new byte[size];
-            } else {
-                if (DataInputStream.byteBuf.length < size) {
-                    DataInputStream.byteBuf = new byte[size];
-                }
-                utfBytes = DataInputStream.byteBuf;
-            }
-            int utfIndex = 0;
-            for (int i = 0; i < length; i++) {
-                int charValue = str.charAt(i);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >>
6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                } else {
-                    utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >>
12)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >>
6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                }
-            }
-            writeShort(utfIndex);
-            write(utfBytes, 0, utfIndex);
-            if (!makeBuf) {
-                DataInputStream.useShared = true;
-            }
-        } else {
-            long utfCount;
-            if (length <= 65535 && (utfCount = countUTFBytes(str)) <= 65535)
{
-                writeShort((int) utfCount);
-                writeUTFBytes(str, utfCount);
-            } else {
-                throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
-            }
+        long utfCount = countUTFBytes(str);
+        if (utfCount > 65535) {
+            throw new UTFDataFormatException(Msg.getString("K0068")); //$NON-NLS-1$
         }
+        writeShort((int) utfCount);
+        writeUTFBytes(str, utfCount);
     }
 
     long countUTFBytes(String str) {
@@ -390,70 +360,23 @@
     }
 
     void writeUTFBytes(String str, long count) throws IOException {
-        boolean single = true;
         int size = (int) count;
-        if (count > DataInputStream.MAX_BUF_SIZE) {
-            single = false;
-            size = DataInputStream.MAX_BUF_SIZE;
-        }
-        byte[] utfBytes;
-        boolean makeBuf = true;
-        if (DataInputStream.useShared) {
-            synchronized (DataInputStream.cacheLock) {
-                if (DataInputStream.useShared) {
-                    DataInputStream.useShared = false;
-                    makeBuf = false;
-                }
-            }
-        }
-        if (makeBuf) {
-            utfBytes = new byte[size];
-        } else {
-            // byteBuf is not protected by the cacheLock, so sample it first
-            utfBytes = DataInputStream.byteBuf;
-            if (utfBytes.length < size) {
-                utfBytes = DataInputStream.byteBuf = new byte[size];
-            }
-        }
-
-        int utfIndex = 0, i = 0, length = str.length();
-        int end = length;
-        while (i < length) {
-            if (!single) {
-                end = i + ((utfBytes.length - utfIndex) / 3);
-                if (end > length) {
-                    end = length;
-                }
-            }
-            for (int j = i; j < end; j++) {
-                int charValue = str.charAt(j);
-                if (charValue > 0 && charValue <= 127) {
-                    utfBytes[utfIndex++] = (byte) charValue;
-                } else if (charValue <= 2047) {
-                    utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >>
6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                } else {
-                    utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >>
12)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >>
6)));
-                    utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
-                }
-            }
-            if (single || utfIndex > utfBytes.length - 300) {
-                write(utfBytes, 0, utfIndex);
-                if (single) {
-                    return;
-                }
-                utfIndex = 0;
-            }
-            i = end;
-        }
-        if (utfIndex > 0) {
-            write(utfBytes, 0, utfIndex);
-        }
-        if (!makeBuf) {
-            // Update the useShared flag optimistically (see DataInputStream
-            // equivalent)
-            DataInputStream.useShared = true;
+        int length = str.length();
+        byte[] utfBytes = new byte[size];
+        int utfIndex = 0;
+        for (int i = 0; i < length; i++) {
+            int charValue = str.charAt(i);
+            if (charValue > 0 && charValue <= 127) {
+                utfBytes[utfIndex++] = (byte) charValue;
+            } else if (charValue <= 2047) {
+                utfBytes[utfIndex++] = (byte) (0xc0 | (0x1f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+            } else {
+                utfBytes[utfIndex++] = (byte) (0xe0 | (0x0f & (charValue >> 12)));
+                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & (charValue >> 6)));
+                utfBytes[utfIndex++] = (byte) (0x80 | (0x3f & charValue));
+             }
         }
+        write(utfBytes, 0, utfIndex);
     }
 }

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectInputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectInputStream.java?view=diff&rev=534747&r1=534746&r2=534747
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectInputStream.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectInputStream.java
Thu May  3 00:56:58 2007
@@ -105,9 +105,6 @@
     // Handle for the current class descriptor
     private Integer descriptorHandle;
 
-    // cache for readResolve methods
-    private IdentityHashMap<Class<?>, Object> readResolveCache;
-
     private static final Hashtable<String, Class<?>> PRIMITIVE_CLASSES = new
Hashtable<String, Class<?>>();
 
     static {
@@ -325,7 +322,6 @@
         primitiveTypes = new DataInputStream(this);
         enableResolve = false;
         this.subclassOverridingImplementation = false;
-        this.readResolveCache = new IdentityHashMap<Class<?>, Object>();
         resetState();
         nestedLevels = 0;
         // So read...() methods can be used by
@@ -1173,13 +1169,12 @@
                 // Object type (array included).
                 String fieldName = fieldDesc.getName();
                 boolean setBack = false;
-                ObjectStreamField field = classDesc.getField(fieldName);
-                if (mustResolve && field == null) {
+                if (mustResolve && fieldDesc == null) {
                     setBack = true;
                     mustResolve = false;
                 }
                 Object toSet;
-                if (field != null && field.isUnshared()) {
+                if (fieldDesc != null && fieldDesc.isUnshared()) {
                     toSet = readUnshared();
                 } else {
                     toSet = readObject();
@@ -1187,9 +1182,9 @@
                 if (setBack) {
                     mustResolve = true;
                 }
-                if (field != null) {
+                if (fieldDesc != null) {
                     if (toSet != null) {
-                        Class<?> fieldType = field.getType();
+                        Class<?> fieldType = fieldDesc.getType();
                         Class<?> valueType = toSet.getClass();
                         if (!fieldType.isAssignableFrom(valueType)) {
                             throw new ClassCastException(Msg.getString(
@@ -1199,7 +1194,7 @@
                                                     + fieldName }));
                         }
                         try {
-                            objSetField(obj, declaringClass, fieldName, field
+                            objSetField(obj, declaringClass, fieldName, fieldDesc
                                     .getTypeString(), toSet);
                         } catch (NoSuchFieldError e) {
                             // Ignored
@@ -1360,11 +1355,9 @@
         if (!ObjectStreamClass.isSerializable(cl)) {
             return;
         }
-
-        final Method readMethod = ObjectStreamClass
-                .getPrivateReadObjectNoDataMethod(cl);
-        if (readMethod != null) {
-            AccessController.doPrivileged(new PriviAction<Object>(readMethod));
+        ObjectStreamClass classDesc = ObjectStreamClass.lookupStreamClass(cl);
+        if (classDesc.hasMethodReadObjectNoData()){
+            final Method readMethod = classDesc.getMethodReadObjectNoData();
             try {
                 readMethod.invoke(object, new Object[0]);
             } catch (InvocationTargetException e) {
@@ -1379,6 +1372,7 @@
                 throw new RuntimeException(e.toString());
             }
         }
+
     }
 
     private void readObjectForClass(Object object, ObjectStreamClass classDesc)
@@ -1390,12 +1384,12 @@
 
         boolean hadWriteMethod = (classDesc.getFlags() & SC_WRITE_METHOD) > 0;
         Class<?> targetClass = classDesc.forClass();
+
         final Method readMethod;
         if (targetClass == null || !mustResolve) {
             readMethod = null;
         } else {
-            readMethod = ObjectStreamClass
-                    .getPrivateReadObjectMethod(targetClass);
+            readMethod = classDesc.getMethodReadObject();
         }
         try {
             if (readMethod != null) {
@@ -1716,10 +1710,8 @@
         // We need to map classDesc to class.
         try {
             newClassDesc.setClass(resolveClass(newClassDesc));
-            // Check SUIDs
-            verifySUID(newClassDesc);
-            // Check base name of the class
-            verifyBaseName(newClassDesc);
+            // Check SUIDs & base name of the class
+            verifyAndInit(newClassDesc);
         } catch (ClassNotFoundException e) {
             if (mustResolve) {
                 throw e;
@@ -1997,39 +1989,24 @@
         }
 
         if (objectClass != null) {
-            Object readResolveMethod = readResolveCache.get(objectClass);
-            if (readResolveMethod != this) {
-                if (readResolveMethod == null) {
-                    final Method readResolve = ObjectStreamClass
-                            .methodReadResolve(objectClass);
-                    if (readResolve == null) {
-                        readResolveCache.put(objectClass, this);
-                        // readResolveMethod must be null here
-                        assert readResolveMethod == null;
+
+            ObjectStreamClass desc = ObjectStreamClass.lookupStreamClass(objectClass);
+            if (desc.hasMethodReadResolve()){
+                Method methodReadResolve = desc.getMethodReadResolve();
+                try {
+                    result = methodReadResolve.invoke(result, (Object[]) null);
+                } catch (IllegalAccessException iae) {
+                } catch (InvocationTargetException ite) {
+                    Throwable target = ite.getTargetException();
+                    if (target instanceof ObjectStreamException) {
+                        throw (ObjectStreamException) target;
+                    } else if (target instanceof Error) {
+                        throw (Error) target;
                     } else {
-                        // Has replacement method
-                        AccessController.doPrivileged(new PriviAction<Object>(
-                                readResolve));
-                        readResolveCache.put(objectClass, readResolve);
-                        readResolveMethod = readResolve;
-                    }
-                }
-                if (readResolveMethod != null) {
-                    try {
-                        result = ((Method) readResolveMethod).invoke(result,
-                                (Object[]) null);
-                    } catch (IllegalAccessException iae) {
-                    } catch (InvocationTargetException ite) {
-                        Throwable target = ite.getTargetException();
-                        if (target instanceof ObjectStreamException) {
-                            throw (ObjectStreamException) target;
-                        } else if (target instanceof Error) {
-                            throw (Error) target;
-                        } else {
-                            throw (RuntimeException) target;
-                        }
+                        throw (RuntimeException) target;
                     }
                 }
+
             }
         }
         // We get here either if class-based replacement was not needed or if it
@@ -2726,8 +2703,10 @@
     }
 
     /**
-     * Verify if the SUID for descriptor <code>loadedStreamClass</code>matches
-     * the SUID of the corresponding loaded class.
+     * Verify if the SUID & the base name for descriptor 
+     * <code>loadedStreamClass</code>matches
+     * the SUID & the base name of the corresponding loaded class and
+     * init private fields.
      * 
      * @param loadedStreamClass
      *            An ObjectStreamClass that was loaded from the stream.
@@ -2735,41 +2714,20 @@
      * @throws InvalidClassException
      *             If the SUID of the stream class does not match the VM class
      */
-    private void verifySUID(ObjectStreamClass loadedStreamClass)
+    private void verifyAndInit(ObjectStreamClass loadedStreamClass)
             throws InvalidClassException {
+
         Class<?> localClass = loadedStreamClass.forClass();
-        // Instances of java.lang.Class are always Serializable, even if their
-        // instances aren't (e.g. java.lang.Object.class). We cannot call lookup
-        // because it returns null if the parameter represents instances that
-        // cannot be serialized, and that is not what we want. If we are loading
-        // an instance of java.lang.Class, we better have the corresponding
-        // ObjectStreamClass.
         ObjectStreamClass localStreamClass = ObjectStreamClass
                 .lookupStreamClass(localClass);
+
         if (loadedStreamClass.getSerialVersionUID() != localStreamClass
                 .getSerialVersionUID()) {
             throw new InvalidClassException(loadedStreamClass.getName(), Msg
                     .getString("K00da", loadedStreamClass, //$NON-NLS-1$
                             localStreamClass));
         }
-    }
 
-    /**
-     * Verify if the base name for descriptor <code>loadedStreamClass</code>
-     * matches the base name of the corresponding loaded class.
-     * 
-     * @param loadedStreamClass
-     *            An ObjectStreamClass that was loaded from the stream.
-     * 
-     * @throws InvalidClassException
-     *             If the base name of the stream class does not match the VM
-     *             class
-     */
-    private void verifyBaseName(ObjectStreamClass loadedStreamClass)
-            throws InvalidClassException {
-        Class<?> localClass = loadedStreamClass.forClass();
-        ObjectStreamClass localStreamClass = ObjectStreamClass
-                .lookupStreamClass(localClass);
         String loadedClassBaseName = getBaseName(loadedStreamClass.getName());
         String localClassBaseName = getBaseName(localStreamClass.getName());
 
@@ -2778,6 +2736,8 @@
                     .getString("KA015", loadedClassBaseName, //$NON-NLS-1$
                             localClassBaseName));
         }
+
+        loadedStreamClass.initPrivateFields(localStreamClass);        
     }
 
     private static String getBaseName(String fullName) {

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectOutputStream.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectOutputStream.java?view=diff&rev=534747&r1=534746&r2=534747
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectOutputStream.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectOutputStream.java
Thu May  3 00:56:58 2007
@@ -105,10 +105,6 @@
      */
     private boolean subclassOverridingImplementation;
 
-    /*
-     * cache for writeReplace methods
-     */
-    private IdentityHashMap<Class<?>, Object> writeReplaceCache;
 
     /**
      * Inner class to provide access to serializable fields
@@ -207,7 +203,6 @@
         this.enableReplace = false;
         this.protocolVersion = PROTOCOL_VERSION_2;
         this.subclassOverridingImplementation = false;
-        this.writeReplaceCache = new IdentityHashMap<Class<?>, Object>();
 
         resetState();
         this.nestedException = new StreamCorruptedException();
@@ -1304,12 +1299,8 @@
         boolean executed = false;
         Class<?> targetClass = classDesc.forClass();
         try {
-            final Method method = ObjectStreamClass
-                    .getPrivateWriteObjectMethod(targetClass);
-            if (method != null) {
-                // We have to be able to fetch its value, even if it is
-                // private
-                AccessController.doPrivileged(new PriviAction<Object>(method));
+            if (classDesc.hasMethodWriteObject()){
+                final Method method = classDesc.getMethodWriteObject();
                 try {
                     method.invoke(object, new Object[] { this });
                     executed = true;
@@ -1326,6 +1317,7 @@
                 }
             }
 
+
             if (executed) {
                 drain();
                 output.writeByte(TC_ENDBLOCKDATA);
@@ -1853,57 +1845,40 @@
 
             if (ObjectStreamClass.isSerializable(object.getClass())
                     && computeClassBasedReplacement) {
-                Object writeReplaceMethod = writeReplaceCache.get(objClass);
-                if (writeReplaceMethod != this) {
-                    if (writeReplaceMethod == null) {
-                        final Method writeReplace = ObjectStreamClass
-                                .methodWriteReplace(objClass);
-                        if (writeReplace == null) {
-                            writeReplaceCache.put(objClass, this);
-                            // writeReplaceMethod must be null here
-                            assert writeReplaceMethod == null;
+                ObjectStreamClass clDesc = ObjectStreamClass.lookupStreamClass(objClass);
+                if(clDesc.hasMethodWriteReplace()){
+                    Method methodWriteReplace = clDesc.getMethodWriteReplace();
+                    Object replObj = null; 
+                    try {
+                        replObj = methodWriteReplace.invoke(object, (Object[]) null);
+                    } catch (IllegalAccessException iae) {
+                        replObj = object;
+                    } catch (InvocationTargetException ite) {
+                        // WARNING - Not sure this is the right thing to do
+                        // if we can't run the method
+                        Throwable target = ite.getTargetException();
+                        if (target instanceof ObjectStreamException) {
+                            throw (ObjectStreamException) target;
+                        } else if (target instanceof Error) {
+                            throw (Error) target;
                         } else {
-                            // Has replacement method
-                            AccessController
-                                    .doPrivileged(new PriviAction<Object>(
-                                            writeReplace));
-                            writeReplaceCache.put(objClass, writeReplace);
-                            writeReplaceMethod = writeReplace;
+                            throw (RuntimeException) target;
                         }
                     }
-                    if (writeReplaceMethod != null) {
-                        Object classBasedReplacement;
-                        try {
-                            classBasedReplacement = ((Method) writeReplaceMethod)
-                                    .invoke(object, (Object[]) null);
-                        } catch (IllegalAccessException iae) {
-                            classBasedReplacement = object;
-                        } catch (InvocationTargetException ite) {
-                            // WARNING - Not sure this is the right thing to do
-                            // if we can't run the method
-                            Throwable target = ite.getTargetException();
-                            if (target instanceof ObjectStreamException) {
-                                throw (ObjectStreamException) target;
-                            } else if (target instanceof Error) {
-                                throw (Error) target;
-                            } else {
-                                throw (RuntimeException) target;
-                            }
-                        }
-                        if (classBasedReplacement != object) {
-                            // All over, class-based replacement off this time.
-                            Integer replacementHandle = writeObjectInternal(
-                                    classBasedReplacement, false, false,
-                                    computeStreamReplacement);
-                            // Make the original object also map to the same
-                            // handle.
-                            if (replacementHandle != null) {
-                                registerObjectWritten(object, replacementHandle);
-                            }
-                            return replacementHandle;
+                    if (replObj != object) {
+                        // All over, class-based replacement off this time.
+                        Integer replacementHandle = writeObjectInternal(
+                                replObj, false, false,
+                                computeStreamReplacement);
+                        // Make the original object also map to the same
+                        // handle.
+                        if (replacementHandle != null) {
+                            registerObjectWritten(object, replacementHandle);
                         }
+                        return replacementHandle;
                     }
                 }
+
             }
 
             // We get here either if class-based replacement was not needed or

Modified: harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectStreamClass.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectStreamClass.java?view=diff&rev=534747&r1=534746&r2=534747
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectStreamClass.java
(original)
+++ harmony/enhanced/classlib/trunk/modules/luni/src/main/java/java/io/ObjectStreamClass.java
Thu May  3 00:56:58 2007
@@ -138,6 +138,12 @@
     // of ObjectStreamClass
     private static final WeakHashMap<Class<?>, ObjectStreamClass> classesAndDescriptors
= new WeakHashMap<Class<?>, ObjectStreamClass>();
 
+    private transient Method methodWriteReplace;
+    private transient Method methodReadResolve;
+    private transient Method methodWriteObject;
+    private transient Method methodReadObject;
+    private transient Method methodReadObjectNoData;
+
     // ClassDesc //
 
     // Name of the class this descriptor represents
@@ -182,8 +188,7 @@
     }
 
     /**
-     * Add an extra entry mapping a given class <code>cl</code> to its class
-     * descriptor, which will be computed (an ObjectStreamClass). If
+     * Compute class descriptor for a given class <code>cl</code>. If
      * <code>computeSUID</code> is true, this method will compute the SUID for
      * this class.
      * 
@@ -194,7 +199,7 @@
      *            a boolean indicating if SUID should be computed or not.
      * @return the computer class descriptor
      */
-    private static ObjectStreamClass addToCache(Class<?> cl, boolean computeSUID) {
+    private static ObjectStreamClass createClassDesc(Class<?> cl, boolean computeSUID)
{
 
         ObjectStreamClass result = new ObjectStreamClass();
 
@@ -234,11 +239,20 @@
         } else if (serializable) {
             flags |= ObjectStreamConstants.SC_SERIALIZABLE;
         }
-        if (getPrivateWriteObjectMethod(cl) != null) {
+        result.methodWriteReplace = 
+            findMethod(cl, "writeReplace");
+        result.methodReadResolve = 
+            findMethod(cl, "readResolve");
+        result.methodWriteObject = 
+            findPrivateMethod(cl, "writeObject", WRITE_PARAM_TYPES);
+        result.methodReadObject = 
+            findPrivateMethod(cl, "readObject", READ_PARAM_TYPES);
+        result.methodReadObjectNoData = 
+            findPrivateMethod(cl, "readObjectNoData", EMPTY_CONSTRUCTOR_PARAM_TYPES); 
+        if (result.hasMethodWriteObject()) {
             flags |= ObjectStreamConstants.SC_WRITE_METHOD;
         }
         result.setFlags(flags);
-        classesAndDescriptors.put(cl, result);
 
         return result;
     }
@@ -633,14 +647,12 @@
      */
     ObjectStreamField[] fields() {
         if (fields == null) {
-            synchronized(this){ 
-                Class<?> forCl = forClass();
-                if (forCl != null && isSerializable(forCl) && !forCl.isArray())
{
-                    buildFieldDescriptors(forCl.getDeclaredFields());
-                } else {
-                    // Externalizables or arrays do not need FieldDesc info
-                    setFields(new ObjectStreamField[0]);
-                }
+            Class<?> forCl = forClass();
+            if (forCl != null && isSerializable(forCl) && !forCl.isArray())
{
+                buildFieldDescriptors(forCl.getDeclaredFields());
+            } else {
+                // Externalizables or arrays do not need FieldDesc info
+                setFields(new ObjectStreamField[0]);
             }
         }
         return fields;
@@ -771,75 +783,6 @@
     private static native boolean hasClinit(Class<?> cl);
 
     /**
-     * Return true if the given class <code>cl</code> implements private
-     * method <code>readObject()</code>.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return <code>true</code> if the class implements readObject
-     *         <code>false</code> if the class does not implement readObject
-     */
-    static Method getPrivateReadObjectMethod(Class<?> cl) {
-        try {
-            Method method = cl
-                    .getDeclaredMethod("readObject", READ_PARAM_TYPES); //$NON-NLS-1$
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
-     * Return true if the given class <code>cl</code> implements private
-     * method <code>readObject()</code>.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return <code>true</code> if the class implements readObject
-     *         <code>false</code> if the class does not implement readObject
-     */
-    static Method getPrivateReadObjectNoDataMethod(Class<?> cl) {
-        try {
-            Method method = cl.getDeclaredMethod("readObjectNoData", //$NON-NLS-1$
-                    EMPTY_CONSTRUCTOR_PARAM_TYPES);
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
-     * Return true if the given class <code>cl</code> implements private
-     * method <code>writeObject()</code>.
-     * 
-     * @param cl
-     *            a java.lang.Class which to test
-     * @return <code>true</code> if the class implements writeObject
-     *         <code>false</code> if the class does not implement writeObject
-     */
-    static Method getPrivateWriteObjectMethod(Class<?> cl) {
-        try {
-            Method method = cl.getDeclaredMethod("writeObject", //$NON-NLS-1$
-                    WRITE_PARAM_TYPES);
-            if (Modifier.isPrivate(method.getModifiers())
-                    && method.getReturnType() == VOID_CLASS) {
-                return method;
-            }
-        } catch (NoSuchMethodException nsm) {
-            // Ignored
-        }
-        return null;
-    }
-
-    /**
      * Return true if instances of class <code>cl</code> are Externalizable,
      * false otherwise.
      * 
@@ -953,37 +896,43 @@
      *            a boolean indicating if SUID should be computed or not.
      * @return the corresponding descriptor
      */
-    private static synchronized ObjectStreamClass lookupStreamClass(
+    private static ObjectStreamClass lookupStreamClass(
             Class<?> cl, boolean computeSUID) {
         // Synchronized because of the lookup table 'classesAndDescriptors'
-        ObjectStreamClass cachedValue = classesAndDescriptors.get(cl);
-        if (cachedValue != null) {
-            return cachedValue;
+
+        ObjectStreamClass cachedValue;  
+        synchronized(classesAndDescriptors){
+            cachedValue = classesAndDescriptors.get(cl);
+            if (cachedValue == null) {
+                cachedValue  = createClassDesc(cl, computeSUID);;
+               classesAndDescriptors.put(cl, cachedValue);
+            }
         }
-        return addToCache(cl, computeSUID);
+        return cachedValue;
+
     }
 
     /**
-     * Return the java.lang.reflect.Method <code>readResolve</code> if class
-     * <code>cl</code> implements it. Return null otherwise.
+     * Return the java.lang.reflect.Method if class
+     * <code>cl</code> implements <code>methodName</code> . Return
null otherwise.
      * 
      * @param cl
      *            a java.lang.Class which to test
      * @return <code>java.lang.reflect.Method</code> if the class implements
-     *         readResolve <code>null</code> if the class does not implement
-     *         readResolve
+     *         writeReplace <code>null</code> if the class does not implement
+     *         writeReplace
      */
-    static Method methodReadResolve(Class<?> cl) {
+    static Method findMethod(Class<?> cl, String methodName) {
         Class<?> search = cl;
+        Method method = null;
         while (search != null) {
             try {
-                Method method = search.getDeclaredMethod(
-                        "readResolve", (Class[]) null); //$NON-NLS-1$
+                method = search.getDeclaredMethod(methodName, (Class[]) null); //$NON-NLS-1$
                 if (search == cl
                         || (method.getModifiers() & Modifier.PRIVATE) == 0) {
+                    method.setAccessible(true);
                     return method;
                 }
-                return null;
             } catch (NoSuchMethodException nsm) {
             }
             search = search.getSuperclass();
@@ -992,8 +941,8 @@
     }
 
     /**
-     * Return the java.lang.reflect.Method <code>writeReplace</code> if class
-     * <code>cl</code> implements it. Return null otherwise.
+     * Return the java.lang.reflect.Method if class
+     * <code>cl</code> implements private <code>methodName</code>
. Return null otherwise.
      * 
      * @param cl
      *            a java.lang.Class which to test
@@ -1001,25 +950,68 @@
      *         writeReplace <code>null</code> if the class does not implement
      *         writeReplace
      */
-    static Method methodWriteReplace(Class<?> cl) {
-        Class<?> search = cl;
-        while (search != null) {
-            try {
-                Method method = search.getDeclaredMethod(
-                        "writeReplace", (Class[]) null); //$NON-NLS-1$
-                if (search == cl
-                        || (method.getModifiers() & Modifier.PRIVATE) == 0) {
-                    return method;
-                }
-                return null;
-            } catch (NoSuchMethodException nsm) {
-                // Ignored
+    static Method findPrivateMethod(Class<?> cl, String methodName, Class[] param)
{
+        try {
+            Method method = cl
+                    .getDeclaredMethod(methodName, param); //$NON-NLS-1$
+            if (Modifier.isPrivate(method.getModifiers())
+                    && method.getReturnType() == VOID_CLASS) {
+                method.setAccessible(true);
+                return method;
             }
-            search = search.getSuperclass();
+        } catch (NoSuchMethodException nsm) {
+            // Ignored
         }
         return null;
     }
 
+    boolean hasMethodWriteReplace(){
+        return (methodWriteReplace != null);
+    }
+
+    Method getMethodWriteReplace(){
+        return methodWriteReplace;
+    }
+
+    boolean hasMethodReadResolve(){
+        return (methodReadResolve != null);
+    }
+
+    Method getMethodReadResolve(){
+        return methodReadResolve;
+    }
+
+    boolean hasMethodWriteObject(){
+        return (methodWriteObject != null);
+    }
+
+    Method getMethodWriteObject(){
+        return methodWriteObject;
+    }
+
+    boolean hasMethodReadObject(){
+        return (methodReadObject != null);
+    }
+
+    Method getMethodReadObject(){
+        return methodReadObject;
+    }
+
+    boolean hasMethodReadObjectNoData(){
+        return (methodReadObjectNoData != null);
+    }
+
+    Method getMethodReadObjectNoData(){
+        return methodReadObjectNoData;
+    }
+
+    void initPrivateFields(ObjectStreamClass desc){
+        methodWriteReplace = desc.methodWriteReplace;
+        methodReadResolve = desc.methodReadResolve;
+        methodWriteObject = desc.methodWriteObject;
+        methodReadObject = desc.methodReadObject;
+        methodReadObjectNoData = desc.methodReadObjectNoData;
+    }
     /**
      * Set the class (java.lang.Class) that the receiver represents
      * 



Mime
View raw message