Hi Jeroen, hi list,

Jeroen Frijters schrieb:
Roman Kennke wrote:
Here comes a significant performance improvement for Zipfile, done by Ingo. It avoids expensive UTF8 decoding when possible (most cases, for ASCII) and optimizes readLeShort() and readLeInt() for the case when the buffer has enough bytes. Mauve shows no regressions.

This looks like it isn't thread safe:
+          UTF8DECODER.reset();
+          char [] characters =
UTF8DECODER.decode(bufferBuffer).array();

Fixed using the attached patch.

2006-08-15  Roman Kennke  <[EMAIL PROTECTED]>

        * java/util/zip/ZipFile.java
        (UTF8DECODER): Removed.
        (UTF8CHARSET): New constant field. Stores the UTF8 charset.
        (utf8Decoder): New instance field.
        (decodeChars): Lazily create UTF8 decoder. Use instance
        field rather than a static field to avoid corruption.

/Roman

Index: java/util/zip/ZipFile.java
===================================================================
RCS file: /cvsroot/classpath/classpath/java/util/zip/ZipFile.java,v
retrieving revision 1.36
diff -u -1 -2 -r1.36 ZipFile.java
--- java/util/zip/ZipFile.java	15 Aug 2006 11:28:10 -0000	1.36
+++ java/util/zip/ZipFile.java	15 Aug 2006 14:22:27 -0000
@@ -511,28 +511,32 @@
     public Object nextElement()
     {
       /* We return a clone, just to be safe that the user doesn't
        * change the entry.  
        */
       return ((ZipEntry)elements.next()).clone();
     }
   }
 
   private static final class PartialInputStream extends InputStream
   {
     /**
-     * The UTF-8 decoder use for decoding the filenames.
+     * The UTF-8 charset use for decoding the filenames.
      */
-    private static final CharsetDecoder UTF8DECODER =
-      Charset.forName("UTF-8").newDecoder();
+    private static final Charset UTF8CHARSET = Charset.forName("UTF-8");
+
+    /**
+     * The actual UTF-8 decoder. Created on demand. 
+     */
+    private CharsetDecoder utf8Decoder;
 
     private final RandomAccessFile raf;
     private final byte[] buffer;
     private long bufferOffset;
     private int pos;
     private long end;
     // We may need to supply an extra dummy byte to our reader.
     // See Inflater.  We use a count here to simplify the logic
     // elsewhere in this class.  Note that we ignore the dummy
     // byte in methods where we know it is not needed.
     private int dummyByteCount;
 
@@ -725,26 +729,28 @@
       int i=length - 1;
       while ((i >= 0) && (buffer[i] <= 0x7f))
         {
           i--;
         }
       if (i < 0)
         {
           result = new String(buffer, 0, pos, length);
         }
       else
         {
           ByteBuffer bufferBuffer = ByteBuffer.wrap(buffer, pos, length);
-          UTF8DECODER.reset();
-          char [] characters = UTF8DECODER.decode(bufferBuffer).array();
+          if (utf8Decoder == null)
+            utf8Decoder = UTF8CHARSET.newDecoder();
+          utf8Decoder.reset();
+          char [] characters = utf8Decoder.decode(bufferBuffer).array();
           result = String.valueOf(characters);
         }
       return result;
     }
 
     String readString(int length) throws IOException
     {
       if (length > end - (bufferOffset + pos))
         throw new EOFException();
 
       String result = null;
       try

Reply via email to