6988106: javac report 'java.lang.IllegalMonitorStateException'

Mon, 24 Jan 2011 16:38:56 -0800

author
jjg
date
Mon, 24 Jan 2011 16:38:56 -0800
changeset 839
a8437c34fdc7
parent 838
22a040cbf0e0
child 840
7f8794f9cc14

6988106: javac report 'java.lang.IllegalMonitorStateException'
Reviewed-by: ksrini

src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/JavacFileManager.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java file | annotate | diff | comparison | revisions
src/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java file | annotate | diff | comparison | revisions
test/tools/javac/T6725036.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java	Mon Jan 24 16:34:25 2011 -0800
     1.2 +++ b/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java	Mon Jan 24 16:38:56 2011 -0800
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -28,10 +28,10 @@
    1.11  import java.io.File;
    1.12  import java.io.IOException;
    1.13  import java.util.List;
    1.14 +import java.util.Map;
    1.15 +import java.util.concurrent.ConcurrentHashMap;
    1.16  
    1.17  import com.sun.tools.javac.util.Context;
    1.18 -import java.util.Map;
    1.19 -import java.util.concurrent.ConcurrentHashMap;
    1.20  
    1.21  /**
    1.22   * Caching implementation of FSInfo.
     2.1 --- a/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Jan 24 16:34:25 2011 -0800
     2.2 +++ b/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java	Mon Jan 24 16:38:56 2011 -0800
     2.3 @@ -76,8 +76,6 @@
     2.4   */
     2.5  public class JavacFileManager extends BaseFileManager implements StandardJavaFileManager {
     2.6  
     2.7 -    boolean useZipFileIndex;
     2.8 -
     2.9      public static char[] toArray(CharBuffer buffer) {
    2.10          if (buffer.hasArray())
    2.11              return ((CharBuffer)buffer.compact().flip()).array();
    2.12 @@ -91,6 +89,9 @@
    2.13  
    2.14      private FSInfo fsInfo;
    2.15  
    2.16 +    private boolean useZipFileIndex;
    2.17 +    private ZipFileIndexCache zipFileIndexCache;
    2.18 +
    2.19      private final File uninited = new File("U N I N I T E D");
    2.20  
    2.21      private final Set<JavaFileObject.Kind> sourceOrClass =
    2.22 @@ -163,7 +164,11 @@
    2.23  
    2.24          fsInfo = FSInfo.instance(context);
    2.25  
    2.26 -        useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null;
    2.27 +        // retain check for system property for compatibility
    2.28 +        useZipFileIndex = options.isUnset("useJavaUtilZip")
    2.29 +                && System.getProperty("useJavaUtilZip") == null;
    2.30 +        if (useZipFileIndex)
    2.31 +            zipFileIndexCache = ZipFileIndexCache.getSharedInstance();
    2.32  
    2.33          mmappedIO = options.isSet("mmappedIO");
    2.34          ignoreSymbolFile = options.isSet("ignore.symbol.file");
    2.35 @@ -526,7 +531,7 @@
    2.36                      archive = new ZipArchive(this, zdir);
    2.37                  } else {
    2.38                      archive = new ZipFileIndexArchive(this,
    2.39 -                                ZipFileIndex.getZipFileIndex(zipFileName,
    2.40 +                                zipFileIndexCache.getZipFileIndex(zipFileName,
    2.41                                      null,
    2.42                                      usePreindexedCache,
    2.43                                      preindexCacheLocation,
    2.44 @@ -538,7 +543,7 @@
    2.45                  }
    2.46                  else {
    2.47                      archive = new ZipFileIndexArchive(this,
    2.48 -                                ZipFileIndex.getZipFileIndex(zipFileName,
    2.49 +                                zipFileIndexCache.getZipFileIndex(zipFileName,
    2.50                                      symbolFilePrefix,
    2.51                                      usePreindexedCache,
    2.52                                      preindexCacheLocation,
     3.1 --- a/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Jan 24 16:34:25 2011 -0800
     3.2 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndex.java	Mon Jan 24 16:38:56 2011 -0800
     3.3 @@ -1,5 +1,5 @@
     3.4  /*
     3.5 - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
     3.6 + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
     3.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.8   *
     3.9   * This code is free software; you can redistribute it and/or modify it
    3.10 @@ -38,11 +38,9 @@
    3.11  import java.util.Collections;
    3.12  import java.util.HashMap;
    3.13  import java.util.HashSet;
    3.14 -import java.util.Iterator;
    3.15  import java.util.List;
    3.16  import java.util.Map;
    3.17  import java.util.Set;
    3.18 -import java.util.concurrent.locks.ReentrantLock;
    3.19  import java.util.zip.DataFormatException;
    3.20  import java.util.zip.Inflater;
    3.21  import java.util.zip.ZipException;
    3.22 @@ -50,24 +48,28 @@
    3.23  import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
    3.24  import com.sun.tools.javac.file.RelativePath.RelativeFile;
    3.25  
    3.26 -/** This class implements building of index of a zip archive and access to it's context.
    3.27 - *  It also uses prebuild index if available. It supports invocations where it will
    3.28 - *  serialize an optimized zip index file to disk.
    3.29 +/**
    3.30 + * This class implements the building of index of a zip archive and access to
    3.31 + * its context. It also uses a prebuilt index if available.
    3.32 + * It supports invocations where it will serialize an optimized zip index file
    3.33 + * to disk.
    3.34   *
    3.35 - *  In oreder to use secondary index file make sure the option "usezipindex" is in the Options object,
    3.36 - *  when JavacFileManager is invoked. (You can pass "-XDusezipindex" on the command line.
    3.37 + * In order to use a secondary index file, set "usezipindex" in the Options
    3.38 + * object when JavacFileManager is invoked. (You can pass "-XDusezipindex" on
    3.39 + * the command line.)
    3.40   *
    3.41 - *  Location where to look for/generate optimized zip index files can be provided using
    3.42 - *  "-XDcachezipindexdir=<directory>". If this flag is not provided, the dfault location is
    3.43 - *  the value of the "java.io.tmpdir" system property.
    3.44 + * Location where to look for/generate optimized zip index files can be
    3.45 + * provided using "-XDcachezipindexdir=<directory>". If this flag is not
    3.46 + * provided, the default location is the value of the "java.io.tmpdir" system
    3.47 + * property.
    3.48   *
    3.49 - *  If key "-XDwritezipindexfiles" is specified, there will be new optimized index file
    3.50 - *  created for each archive, used by the compiler for compilation, at location,
    3.51 - *  specified by "cachezipindexdir" option.
    3.52 + * If "-XDwritezipindexfiles" is specified, there will be new optimized index
    3.53 + * file created for each archive, used by the compiler for compilation, at the
    3.54 + * location specified by the "cachezipindexdir" option.
    3.55   *
    3.56 - * If nonBatchMode option is specified (-XDnonBatchMode) the compiler will use timestamp
    3.57 - * checking to reindex the zip files if it is needed. In batch mode the timestamps are not checked
    3.58 - * and the compiler uses the cached indexes.
    3.59 + * If system property nonBatchMode option is specified the compiler will use
    3.60 + * timestamp checking to reindex the zip files if it is needed. In batch mode
    3.61 + * the timestamps are not checked and the compiler uses the cached indexes.
    3.62   *
    3.63   * <p><b>This is NOT part of any supported API.
    3.64   * If you write code that depends on this, you do so at your own risk.
    3.65 @@ -80,18 +82,18 @@
    3.66  
    3.67      public final static long NOT_MODIFIED = Long.MIN_VALUE;
    3.68  
    3.69 -    private static Map<File, ZipFileIndex> zipFileIndexCache = new HashMap<File, ZipFileIndex>();
    3.70 -    private static ReentrantLock lock = new ReentrantLock();
    3.71  
    3.72      private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this.
    3.73  
    3.74 -    private Map<RelativeDirectory, DirectoryEntry> directories = Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
    3.75 -    private Set<RelativeDirectory> allDirs = Collections.<RelativeDirectory>emptySet();
    3.76 +    private Map<RelativeDirectory, DirectoryEntry> directories =
    3.77 +            Collections.<RelativeDirectory, DirectoryEntry>emptyMap();
    3.78 +    private Set<RelativeDirectory> allDirs =
    3.79 +            Collections.<RelativeDirectory>emptySet();
    3.80  
    3.81      // ZipFileIndex data entries
    3.82 -    private File zipFile;
    3.83 +    final File zipFile;
    3.84      private Reference<File> absFileRef;
    3.85 -    private long zipFileLastModified = NOT_MODIFIED;
    3.86 +    long zipFileLastModified = NOT_MODIFIED;
    3.87      private RandomAccessFile zipRandomFile;
    3.88      private Entry[] entries;
    3.89  
    3.90 @@ -99,156 +101,24 @@
    3.91      private File zipIndexFile = null;
    3.92      private boolean triedToReadIndex = false;
    3.93      final RelativeDirectory symbolFilePrefix;
    3.94 -    private int symbolFilePrefixLength = 0;
    3.95 +    private final int symbolFilePrefixLength;
    3.96      private boolean hasPopulatedData = false;
    3.97 -    private long lastReferenceTimeStamp = NOT_MODIFIED;
    3.98 +    long lastReferenceTimeStamp = NOT_MODIFIED;
    3.99  
   3.100 -    private boolean usePreindexedCache = false;
   3.101 -    private String preindexedCacheLocation = null;
   3.102 +    private final boolean usePreindexedCache;
   3.103 +    private final String preindexedCacheLocation;
   3.104  
   3.105      private boolean writeIndex = false;
   3.106  
   3.107 -    private Map <String, SoftReference<RelativeDirectory>> relativeDirectoryCache =
   3.108 +    private Map<String, SoftReference<RelativeDirectory>> relativeDirectoryCache =
   3.109              new HashMap<String, SoftReference<RelativeDirectory>>();
   3.110  
   3.111 -    /**
   3.112 -     * Returns a list of all ZipFileIndex entries
   3.113 -     *
   3.114 -     * @return A list of ZipFileIndex entries, or an empty list
   3.115 -     */
   3.116 -    public static List<ZipFileIndex> getZipFileIndexes() {
   3.117 -        return getZipFileIndexes(false);
   3.118 +
   3.119 +    public synchronized boolean isOpen() {
   3.120 +        return (zipRandomFile != null);
   3.121      }
   3.122  
   3.123 -    /**
   3.124 -     * Returns a list of all ZipFileIndex entries
   3.125 -     *
   3.126 -     * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
   3.127 -     *                   all ZipFileEntry(s) are included into the list.
   3.128 -     * @return A list of ZipFileIndex entries, or an empty list
   3.129 -     */
   3.130 -    public static List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
   3.131 -        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
   3.132 -        lock.lock();
   3.133 -        try {
   3.134 -            zipFileIndexes.addAll(zipFileIndexCache.values());
   3.135 -
   3.136 -            if (openedOnly) {
   3.137 -                for(ZipFileIndex elem : zipFileIndexes) {
   3.138 -                    if (!elem.isOpen()) {
   3.139 -                        zipFileIndexes.remove(elem);
   3.140 -                    }
   3.141 -                }
   3.142 -            }
   3.143 -        }
   3.144 -        finally {
   3.145 -            lock.unlock();
   3.146 -        }
   3.147 -        return zipFileIndexes;
   3.148 -    }
   3.149 -
   3.150 -    public boolean isOpen() {
   3.151 -        lock.lock();
   3.152 -        try {
   3.153 -            return zipRandomFile != null;
   3.154 -        }
   3.155 -        finally {
   3.156 -            lock.unlock();
   3.157 -        }
   3.158 -    }
   3.159 -
   3.160 -    public static ZipFileIndex getZipFileIndex(File zipFile,
   3.161 -            RelativeDirectory symbolFilePrefix,
   3.162 -            boolean useCache, String cacheLocation,
   3.163 -            boolean writeIndex) throws IOException {
   3.164 -        ZipFileIndex zi = null;
   3.165 -        lock.lock();
   3.166 -        try {
   3.167 -            zi = getExistingZipIndex(zipFile);
   3.168 -
   3.169 -            if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
   3.170 -                zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex,
   3.171 -                        useCache, cacheLocation);
   3.172 -                zipFileIndexCache.put(zipFile, zi);
   3.173 -            }
   3.174 -        }
   3.175 -        finally {
   3.176 -            lock.unlock();
   3.177 -        }
   3.178 -        return zi;
   3.179 -    }
   3.180 -
   3.181 -    public static ZipFileIndex getExistingZipIndex(File zipFile) {
   3.182 -        lock.lock();
   3.183 -        try {
   3.184 -            return zipFileIndexCache.get(zipFile);
   3.185 -        }
   3.186 -        finally {
   3.187 -            lock.unlock();
   3.188 -        }
   3.189 -    }
   3.190 -
   3.191 -    public static void clearCache() {
   3.192 -        lock.lock();
   3.193 -        try {
   3.194 -            zipFileIndexCache.clear();
   3.195 -        }
   3.196 -        finally {
   3.197 -            lock.unlock();
   3.198 -        }
   3.199 -    }
   3.200 -
   3.201 -    public static void clearCache(long timeNotUsed) {
   3.202 -        lock.lock();
   3.203 -        try {
   3.204 -            Iterator<File> cachedFileIterator = zipFileIndexCache.keySet().iterator();
   3.205 -            while (cachedFileIterator.hasNext()) {
   3.206 -                File cachedFile = cachedFileIterator.next();
   3.207 -                ZipFileIndex cachedZipIndex = zipFileIndexCache.get(cachedFile);
   3.208 -                if (cachedZipIndex != null) {
   3.209 -                    long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
   3.210 -                    if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
   3.211 -                            System.currentTimeMillis() > timeToTest) {
   3.212 -                        zipFileIndexCache.remove(cachedFile);
   3.213 -                    }
   3.214 -                }
   3.215 -            }
   3.216 -        }
   3.217 -        finally {
   3.218 -            lock.unlock();
   3.219 -        }
   3.220 -    }
   3.221 -
   3.222 -    public static void removeFromCache(File file) {
   3.223 -        lock.lock();
   3.224 -        try {
   3.225 -            zipFileIndexCache.remove(file);
   3.226 -        }
   3.227 -        finally {
   3.228 -            lock.unlock();
   3.229 -        }
   3.230 -    }
   3.231 -
   3.232 -    /** Sets already opened list of ZipFileIndexes from an outside client
   3.233 -      * of the compiler. This functionality should be used in a non-batch clients of the compiler.
   3.234 -      */
   3.235 -    public static void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
   3.236 -        lock.lock();
   3.237 -        try {
   3.238 -            if (zipFileIndexCache.isEmpty()) {
   3.239 -                throw new IllegalStateException("Setting opened indexes should be called only when the ZipFileCache is empty. Call JavacFileManager.flush() before calling this method.");
   3.240 -            }
   3.241 -
   3.242 -            for (ZipFileIndex zfi : indexes) {
   3.243 -                zipFileIndexCache.put(zfi.zipFile, zfi);
   3.244 -            }
   3.245 -        }
   3.246 -        finally {
   3.247 -            lock.unlock();
   3.248 -        }
   3.249 -    }
   3.250 -
   3.251 -    private ZipFileIndex(File zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex,
   3.252 +    ZipFileIndex(File zipFile, RelativeDirectory symbolFilePrefix, boolean writeIndex,
   3.253              boolean useCache, String cacheLocation) throws IOException {
   3.254          this.zipFile = zipFile;
   3.255          this.symbolFilePrefix = symbolFilePrefix;
   3.256 @@ -266,19 +136,22 @@
   3.257          checkIndex();
   3.258      }
   3.259  
   3.260 +    @Override
   3.261      public String toString() {
   3.262          return "ZipFileIndex[" + zipFile + "]";
   3.263      }
   3.264  
   3.265      // Just in case...
   3.266 -    protected void finalize() {
   3.267 +    @Override
   3.268 +    protected void finalize() throws Throwable {
   3.269          closeFile();
   3.270 +        super.finalize();
   3.271      }
   3.272  
   3.273      private boolean isUpToDate() {
   3.274 -        if (zipFile != null &&
   3.275 -                ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified()) &&
   3.276 -                hasPopulatedData) {
   3.277 +        if (zipFile != null
   3.278 +                && ((!NON_BATCH_MODE) || zipFileLastModified == zipFile.lastModified())
   3.279 +                && hasPopulatedData) {
   3.280              return true;
   3.281          }
   3.282  
   3.283 @@ -339,15 +212,9 @@
   3.284          allDirs = Collections.<RelativeDirectory>emptySet();
   3.285      }
   3.286  
   3.287 -    public void close() {
   3.288 -        lock.lock();
   3.289 -        try {
   3.290 -            writeIndex();
   3.291 -            closeFile();
   3.292 -        }
   3.293 -        finally {
   3.294 -            lock.unlock();
   3.295 -        }
   3.296 +    public synchronized void close() {
   3.297 +        writeIndex();
   3.298 +        closeFile();
   3.299      }
   3.300  
   3.301      private void closeFile() {
   3.302 @@ -361,29 +228,24 @@
   3.303      }
   3.304  
   3.305      /**
   3.306 -     * Returns the ZipFileIndexEntry for an absolute path, if there is one.
   3.307 +     * Returns the ZipFileIndexEntry for a path, if there is one.
   3.308       */
   3.309 -    Entry getZipIndexEntry(RelativePath path) {
   3.310 -        lock.lock();
   3.311 +    synchronized Entry getZipIndexEntry(RelativePath path) {
   3.312          try {
   3.313              checkIndex();
   3.314              DirectoryEntry de = directories.get(path.dirname());
   3.315              String lookFor = path.basename();
   3.316 -            return de == null ? null : de.getEntry(lookFor);
   3.317 +            return (de == null) ? null : de.getEntry(lookFor);
   3.318          }
   3.319          catch (IOException e) {
   3.320              return null;
   3.321          }
   3.322 -        finally {
   3.323 -            lock.unlock();
   3.324 -        }
   3.325      }
   3.326  
   3.327      /**
   3.328 -     * Returns a javac List of filenames within an absolute path in the ZipFileIndex.
   3.329 +     * Returns a javac List of filenames within a directory in the ZipFileIndex.
   3.330       */
   3.331 -    public com.sun.tools.javac.util.List<String> getFiles(RelativeDirectory path) {
   3.332 -        lock.lock();
   3.333 +    public synchronized com.sun.tools.javac.util.List<String> getFiles(RelativeDirectory path) {
   3.334          try {
   3.335              checkIndex();
   3.336  
   3.337 @@ -398,13 +260,9 @@
   3.338          catch (IOException e) {
   3.339              return com.sun.tools.javac.util.List.<String>nil();
   3.340          }
   3.341 -        finally {
   3.342 -            lock.unlock();
   3.343 -        }
   3.344      }
   3.345  
   3.346 -    public List<String> getDirectories(RelativeDirectory path) {
   3.347 -        lock.lock();
   3.348 +    public synchronized List<String> getDirectories(RelativeDirectory path) {
   3.349          try {
   3.350              checkIndex();
   3.351  
   3.352 @@ -420,13 +278,9 @@
   3.353          catch (IOException e) {
   3.354              return com.sun.tools.javac.util.List.<String>nil();
   3.355          }
   3.356 -        finally {
   3.357 -            lock.unlock();
   3.358 -        }
   3.359      }
   3.360  
   3.361 -    public Set<RelativeDirectory> getAllDirectories() {
   3.362 -        lock.lock();
   3.363 +    public synchronized Set<RelativeDirectory> getAllDirectories() {
   3.364          try {
   3.365              checkIndex();
   3.366              if (allDirs == Collections.EMPTY_SET) {
   3.367 @@ -438,9 +292,6 @@
   3.368          catch (IOException e) {
   3.369              return Collections.<RelativeDirectory>emptySet();
   3.370          }
   3.371 -        finally {
   3.372 -            lock.unlock();
   3.373 -        }
   3.374      }
   3.375  
   3.376      /**
   3.377 @@ -450,8 +301,7 @@
   3.378       * @param path A path within the zip.
   3.379       * @return True if the path is a file or dir, false otherwise.
   3.380       */
   3.381 -    public boolean contains(RelativePath path) {
   3.382 -        lock.lock();
   3.383 +    public synchronized boolean contains(RelativePath path) {
   3.384          try {
   3.385              checkIndex();
   3.386              return getZipIndexEntry(path) != null;
   3.387 @@ -459,114 +309,69 @@
   3.388          catch (IOException e) {
   3.389              return false;
   3.390          }
   3.391 -        finally {
   3.392 -            lock.unlock();
   3.393 +    }
   3.394 +
   3.395 +    public synchronized boolean isDirectory(RelativePath path) throws IOException {
   3.396 +        // The top level in a zip file is always a directory.
   3.397 +        if (path.getPath().length() == 0) {
   3.398 +            lastReferenceTimeStamp = System.currentTimeMillis();
   3.399 +            return true;
   3.400 +        }
   3.401 +
   3.402 +        checkIndex();
   3.403 +        return directories.get(path) != null;
   3.404 +    }
   3.405 +
   3.406 +    public synchronized long getLastModified(RelativeFile path) throws IOException {
   3.407 +        Entry entry = getZipIndexEntry(path);
   3.408 +        if (entry == null)
   3.409 +            throw new FileNotFoundException();
   3.410 +        return entry.getLastModified();
   3.411 +    }
   3.412 +
   3.413 +    public synchronized int length(RelativeFile path) throws IOException {
   3.414 +        Entry entry = getZipIndexEntry(path);
   3.415 +        if (entry == null)
   3.416 +            throw new FileNotFoundException();
   3.417 +
   3.418 +        if (entry.isDir) {
   3.419 +            return 0;
   3.420 +        }
   3.421 +
   3.422 +        byte[] header = getHeader(entry);
   3.423 +        // entry is not compressed?
   3.424 +        if (get2ByteLittleEndian(header, 8) == 0) {
   3.425 +            return entry.compressedSize;
   3.426 +        } else {
   3.427 +            return entry.size;
   3.428          }
   3.429      }
   3.430  
   3.431 -    public boolean isDirectory(RelativePath path) throws IOException {
   3.432 -        lock.lock();
   3.433 -        try {
   3.434 -            // The top level in a zip file is always a directory.
   3.435 -            if (path.getPath().length() == 0) {
   3.436 -                lastReferenceTimeStamp = System.currentTimeMillis();
   3.437 -                return true;
   3.438 -            }
   3.439 -
   3.440 -            checkIndex();
   3.441 -            return directories.get(path) != null;
   3.442 -        }
   3.443 -        finally {
   3.444 -            lock.unlock();
   3.445 -        }
   3.446 +    public synchronized byte[] read(RelativeFile path) throws IOException {
   3.447 +        Entry entry = getZipIndexEntry(path);
   3.448 +        if (entry == null)
   3.449 +            throw new FileNotFoundException("Path not found in ZIP: " + path.path);
   3.450 +        return read(entry);
   3.451      }
   3.452  
   3.453 -    public long getLastModified(RelativeFile path) throws IOException {
   3.454 -        lock.lock();
   3.455 -        try {
   3.456 -            Entry entry = getZipIndexEntry(path);
   3.457 -            if (entry == null)
   3.458 -                throw new FileNotFoundException();
   3.459 -            return entry.getLastModified();
   3.460 -        }
   3.461 -        finally {
   3.462 -            lock.unlock();
   3.463 -        }
   3.464 +    synchronized byte[] read(Entry entry) throws IOException {
   3.465 +        openFile();
   3.466 +        byte[] result = readBytes(entry);
   3.467 +        closeFile();
   3.468 +        return result;
   3.469      }
   3.470  
   3.471 -    public int length(RelativeFile path) throws IOException {
   3.472 -        lock.lock();
   3.473 -        try {
   3.474 -            Entry entry = getZipIndexEntry(path);
   3.475 -            if (entry == null)
   3.476 -                throw new FileNotFoundException();
   3.477 -
   3.478 -            if (entry.isDir) {
   3.479 -                return 0;
   3.480 -            }
   3.481 -
   3.482 -            byte[] header = getHeader(entry);
   3.483 -            // entry is not compressed?
   3.484 -            if (get2ByteLittleEndian(header, 8) == 0) {
   3.485 -                return entry.compressedSize;
   3.486 -            } else {
   3.487 -                return entry.size;
   3.488 -            }
   3.489 -        }
   3.490 -        finally {
   3.491 -            lock.unlock();
   3.492 -        }
   3.493 +    public synchronized int read(RelativeFile path, byte[] buffer) throws IOException {
   3.494 +        Entry entry = getZipIndexEntry(path);
   3.495 +        if (entry == null)
   3.496 +            throw new FileNotFoundException();
   3.497 +        return read(entry, buffer);
   3.498      }
   3.499  
   3.500 -    public byte[] read(RelativeFile path) throws IOException {
   3.501 -        lock.lock();
   3.502 -        try {
   3.503 -            Entry entry = getZipIndexEntry(path);
   3.504 -            if (entry == null)
   3.505 -                throw new FileNotFoundException("Path not found in ZIP: " + path.path);
   3.506 -            return read(entry);
   3.507 -        }
   3.508 -        finally {
   3.509 -            lock.unlock();
   3.510 -        }
   3.511 -    }
   3.512 -
   3.513 -    byte[] read(Entry entry) throws IOException {
   3.514 -        lock.lock();
   3.515 -        try {
   3.516 -            openFile();
   3.517 -            byte[] result = readBytes(entry);
   3.518 -            closeFile();
   3.519 -            return result;
   3.520 -        }
   3.521 -        finally {
   3.522 -            lock.unlock();
   3.523 -        }
   3.524 -    }
   3.525 -
   3.526 -    public int read(RelativeFile path, byte[] buffer) throws IOException {
   3.527 -        lock.lock();
   3.528 -        try {
   3.529 -            Entry entry = getZipIndexEntry(path);
   3.530 -            if (entry == null)
   3.531 -                throw new FileNotFoundException();
   3.532 -            return read(entry, buffer);
   3.533 -        }
   3.534 -        finally {
   3.535 -            lock.unlock();
   3.536 -        }
   3.537 -    }
   3.538 -
   3.539 -    int read(Entry entry, byte[] buffer)
   3.540 +    synchronized int read(Entry entry, byte[] buffer)
   3.541              throws IOException {
   3.542 -        lock.lock();
   3.543 -        try {
   3.544 -            int result = readBytes(entry, buffer);
   3.545 -            return result;
   3.546 -        }
   3.547 -        finally {
   3.548 -            lock.unlock();
   3.549 -        }
   3.550 +        int result = readBytes(entry, buffer);
   3.551 +        return  result;
   3.552      }
   3.553  
   3.554      private byte[] readBytes(Entry entry) throws IOException {
   3.555 @@ -638,21 +443,20 @@
   3.556    /*
   3.557     * Inflate using the java.util.zip.Inflater class
   3.558     */
   3.559 -    private static Inflater inflater;
   3.560 +    private SoftReference<Inflater> inflaterRef;
   3.561      private int inflate(byte[] src, byte[] dest) {
   3.562 +        Inflater inflater = (inflaterRef == null ? null : inflaterRef.get());
   3.563  
   3.564          // construct the inflater object or reuse an existing one
   3.565          if (inflater == null)
   3.566 -            inflater = new Inflater(true);
   3.567 +            inflaterRef = new SoftReference<Inflater>(inflater = new Inflater(true));
   3.568  
   3.569 -        synchronized (inflater) {
   3.570 -            inflater.reset();
   3.571 -            inflater.setInput(src);
   3.572 -            try {
   3.573 -                return inflater.inflate(dest);
   3.574 -            } catch (DataFormatException ex) {
   3.575 -                return -1;
   3.576 -            }
   3.577 +        inflater.reset();
   3.578 +        inflater.setInput(src);
   3.579 +        try {
   3.580 +            return inflater.inflate(dest);
   3.581 +        } catch (DataFormatException ex) {
   3.582 +            return -1;
   3.583          }
   3.584      }
   3.585  
   3.586 @@ -855,14 +659,10 @@
   3.587       * @return long
   3.588       */
   3.589      public long getZipFileLastModified() throws IOException {
   3.590 -        lock.lock();
   3.591 -        try {
   3.592 +        synchronized (this) {
   3.593              checkIndex();
   3.594              return zipFileLastModified;
   3.595          }
   3.596 -        finally {
   3.597 -            lock.unlock();
   3.598 -        }
   3.599      }
   3.600  
   3.601      /** ------------------------------------------------------------------------
   3.602 @@ -1028,8 +828,7 @@
   3.603          }
   3.604  
   3.605          boolean ret = false;
   3.606 -        lock.lock();
   3.607 -        try {
   3.608 +        synchronized (this) {
   3.609              triedToReadIndex = true;
   3.610              RandomAccessFile raf = null;
   3.611              try {
   3.612 @@ -1071,9 +870,6 @@
   3.613                  readFromIndex = true;
   3.614              }
   3.615          }
   3.616 -        finally {
   3.617 -            lock.unlock();
   3.618 -        }
   3.619  
   3.620          return ret;
   3.621      }
   3.622 @@ -1144,8 +940,8 @@
   3.623                  raf.seek(currFP);
   3.624  
   3.625                  // Now write each of the files in the DirectoryEntry
   3.626 -                List<Entry> entries = de.getEntriesAsCollection();
   3.627 -                for (Entry zfie : entries) {
   3.628 +                List<Entry> list = de.getEntriesAsCollection();
   3.629 +                for (Entry zfie : list) {
   3.630                      // Write the name bytes
   3.631                      byte [] zfieNameBytes = zfie.name.getBytes("UTF-8");
   3.632                      int zfieNameBytesLen = zfieNameBytes.length;
   3.633 @@ -1191,13 +987,9 @@
   3.634      }
   3.635  
   3.636      public boolean writeZipIndex() {
   3.637 -        lock.lock();
   3.638 -        try {
   3.639 +        synchronized (this) {
   3.640              return writeIndex();
   3.641          }
   3.642 -        finally {
   3.643 -            lock.unlock();
   3.644 -        }
   3.645      }
   3.646  
   3.647      private File getIndexFile() {
   3.648 @@ -1328,7 +1120,7 @@
   3.649              return hash;
   3.650          }
   3.651  
   3.652 -
   3.653 +        @Override
   3.654          public String toString() {
   3.655              return isDir ? ("Dir:" + dir + " : " + name) :
   3.656                  (dir + ":" + name);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/share/classes/com/sun/tools/javac/file/ZipFileIndexCache.java	Mon Jan 24 16:38:56 2011 -0800
     4.3 @@ -0,0 +1,149 @@
     4.4 +/*
     4.5 + * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
     4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.7 + *
     4.8 + * This code is free software; you can redistribute it and/or modify it
     4.9 + * under the terms of the GNU General Public License version 2 only, as
    4.10 + * published by the Free Software Foundation.  Oracle designates this
    4.11 + * particular file as subject to the "Classpath" exception as provided
    4.12 + * by Oracle in the LICENSE file that accompanied this code.
    4.13 + *
    4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    4.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    4.17 + * version 2 for more details (a copy is included in the LICENSE file that
    4.18 + * accompanied this code).
    4.19 + *
    4.20 + * You should have received a copy of the GNU General Public License version
    4.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    4.23 + *
    4.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    4.25 + * or visit www.oracle.com if you need additional information or have any
    4.26 + * questions.
    4.27 + */
    4.28 +
    4.29 +package com.sun.tools.javac.file;
    4.30 +
    4.31 +import com.sun.tools.javac.file.RelativePath.RelativeDirectory;
    4.32 +import com.sun.tools.javac.util.Context;
    4.33 +import java.io.File;
    4.34 +import java.io.IOException;
    4.35 +import java.util.ArrayList;
    4.36 +import java.util.HashMap;
    4.37 +import java.util.Iterator;
    4.38 +import java.util.List;
    4.39 +import java.util.Map;
    4.40 +
    4.41 +
    4.42 +/** A cache for ZipFileIndex objects. */
    4.43 +public class ZipFileIndexCache {
    4.44 +
    4.45 +    private final Map<File, ZipFileIndex> map =
    4.46 +            new HashMap<File, ZipFileIndex>();
    4.47 +
    4.48 +    /** Get a shared instance of the cache. */
    4.49 +    private static ZipFileIndexCache sharedInstance;
    4.50 +    public synchronized static ZipFileIndexCache getSharedInstance() {
    4.51 +        if (sharedInstance == null)
    4.52 +            sharedInstance = new ZipFileIndexCache();
    4.53 +        return sharedInstance;
    4.54 +    }
    4.55 +
    4.56 +    /** Get a context-specific instance of a cache. */
    4.57 +    public static ZipFileIndexCache instance(Context context) {
    4.58 +        ZipFileIndexCache instance = context.get(ZipFileIndexCache.class);
    4.59 +        if (instance == null)
    4.60 +            context.put(ZipFileIndexCache.class, instance = new ZipFileIndexCache());
    4.61 +        return instance;
    4.62 +    }
    4.63 +
    4.64 +    /**
    4.65 +     * Returns a list of all ZipFileIndex entries
    4.66 +     *
    4.67 +     * @return A list of ZipFileIndex entries, or an empty list
    4.68 +     */
    4.69 +    public List<ZipFileIndex> getZipFileIndexes() {
    4.70 +        return getZipFileIndexes(false);
    4.71 +    }
    4.72 +
    4.73 +    /**
    4.74 +     * Returns a list of all ZipFileIndex entries
    4.75 +     *
    4.76 +     * @param openedOnly If true it returns a list of only opened ZipFileIndex entries, otherwise
    4.77 +     *                   all ZipFileEntry(s) are included into the list.
    4.78 +     * @return A list of ZipFileIndex entries, or an empty list
    4.79 +     */
    4.80 +    public synchronized List<ZipFileIndex> getZipFileIndexes(boolean openedOnly) {
    4.81 +        List<ZipFileIndex> zipFileIndexes = new ArrayList<ZipFileIndex>();
    4.82 +
    4.83 +        zipFileIndexes.addAll(map.values());
    4.84 +
    4.85 +        if (openedOnly) {
    4.86 +            for(ZipFileIndex elem : zipFileIndexes) {
    4.87 +                if (!elem.isOpen()) {
    4.88 +                    zipFileIndexes.remove(elem);
    4.89 +                }
    4.90 +            }
    4.91 +        }
    4.92 +
    4.93 +        return zipFileIndexes;
    4.94 +    }
    4.95 +
    4.96 +    public synchronized ZipFileIndex getZipFileIndex(File zipFile,
    4.97 +            RelativeDirectory symbolFilePrefix,
    4.98 +            boolean useCache, String cacheLocation,
    4.99 +            boolean writeIndex) throws IOException {
   4.100 +        ZipFileIndex zi = getExistingZipIndex(zipFile);
   4.101 +
   4.102 +        if (zi == null || (zi != null && zipFile.lastModified() != zi.zipFileLastModified)) {
   4.103 +            zi = new ZipFileIndex(zipFile, symbolFilePrefix, writeIndex,
   4.104 +                    useCache, cacheLocation);
   4.105 +            map.put(zipFile, zi);
   4.106 +        }
   4.107 +        return zi;
   4.108 +    }
   4.109 +
   4.110 +    public synchronized ZipFileIndex getExistingZipIndex(File zipFile) {
   4.111 +        return map.get(zipFile);
   4.112 +    }
   4.113 +
   4.114 +    public synchronized void clearCache() {
   4.115 +        map.clear();
   4.116 +    }
   4.117 +
   4.118 +    public synchronized void clearCache(long timeNotUsed) {
   4.119 +        Iterator<File> cachedFileIterator = map.keySet().iterator();
   4.120 +        while (cachedFileIterator.hasNext()) {
   4.121 +            File cachedFile = cachedFileIterator.next();
   4.122 +            ZipFileIndex cachedZipIndex = map.get(cachedFile);
   4.123 +            if (cachedZipIndex != null) {
   4.124 +                long timeToTest = cachedZipIndex.lastReferenceTimeStamp + timeNotUsed;
   4.125 +                if (timeToTest < cachedZipIndex.lastReferenceTimeStamp || // Overflow...
   4.126 +                        System.currentTimeMillis() > timeToTest) {
   4.127 +                    map.remove(cachedFile);
   4.128 +                }
   4.129 +            }
   4.130 +        }
   4.131 +    }
   4.132 +
   4.133 +    public synchronized void removeFromCache(File file) {
   4.134 +        map.remove(file);
   4.135 +    }
   4.136 +
   4.137 +    /** Sets already opened list of ZipFileIndexes from an outside client
   4.138 +      * of the compiler. This functionality should be used in a non-batch clients of the compiler.
   4.139 +      */
   4.140 +    public synchronized void setOpenedIndexes(List<ZipFileIndex>indexes) throws IllegalStateException {
   4.141 +        if (map.isEmpty()) {
   4.142 +            String msg =
   4.143 +                    "Setting opened indexes should be called only when the ZipFileCache is empty. "
   4.144 +                    + "Call JavacFileManager.flush() before calling this method.";
   4.145 +            throw new IllegalStateException(msg);
   4.146 +        }
   4.147 +
   4.148 +        for (ZipFileIndex zfi : indexes) {
   4.149 +            map.put(zfi.zipFile, zfi);
   4.150 +        }
   4.151 +    }
   4.152 +}
     5.1 --- a/test/tools/javac/T6725036.java	Mon Jan 24 16:34:25 2011 -0800
     5.2 +++ b/test/tools/javac/T6725036.java	Mon Jan 24 16:38:56 2011 -0800
     5.3 @@ -1,5 +1,5 @@
     5.4  /*
     5.5 - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved.
     5.6 + * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
     5.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     5.8   *
     5.9   * This code is free software; you can redistribute it and/or modify it
    5.10 @@ -38,6 +38,7 @@
    5.11  import com.sun.tools.javac.file.RelativePath.RelativeFile;
    5.12  import com.sun.tools.javac.file.ZipFileIndex;
    5.13  import com.sun.tools.javac.file.ZipFileIndexArchive;
    5.14 +import com.sun.tools.javac.file.ZipFileIndexCache;
    5.15  import com.sun.tools.javac.util.Context;
    5.16  
    5.17  public class T6725036 {
    5.18 @@ -57,8 +58,8 @@
    5.19          JarEntry je = j.getJarEntry(TEST_ENTRY_NAME.getPath());
    5.20          long jarEntryTime = je.getTime();
    5.21  
    5.22 -        ZipFileIndex zfi =
    5.23 -                ZipFileIndex.getZipFileIndex(rt_jar, null, false, null, false);
    5.24 +        ZipFileIndexCache zfic = ZipFileIndexCache.getSharedInstance();
    5.25 +        ZipFileIndex zfi = zfic.getZipFileIndex(rt_jar, null, false, null, false);
    5.26          long zfiTime = zfi.getLastModified(TEST_ENTRY_NAME);
    5.27  
    5.28          check(je, jarEntryTime, zfi + ":" + TEST_ENTRY_NAME.getPath(), zfiTime);

mercurial