Mon, 24 Jan 2011 16:38:56 -0800
6988106: javac report 'java.lang.IllegalMonitorStateException'
Reviewed-by: ksrini
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);