# HG changeset patch # User jjg # Date 1220463985 25200 # Node ID 5072b0dd3d52736b4b802c09989ef2642330bcb6 # Parent 3a05355982a9eaed7dd0f7c187d2d8e6ec903cce 6743107: clean up use of static caches in file manager Reviewed-by: mcimadamore diff -r 3a05355982a9 -r 5072b0dd3d52 langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/CacheFSInfo.java Wed Sep 03 10:46:25 2008 -0700 @@ -0,0 +1,122 @@ +/* + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package com.sun.tools.javac.file; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import com.sun.tools.javac.util.Context; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Caching implementation of FSInfo + */ +public class CacheFSInfo extends FSInfo { + + /** + * Register a Context.Factory to create a singleton CacheFSInfo. + */ + public static void preRegister(final Context context) { + context.put(FSInfo.class, new Context.Factory() { + public FSInfo make() { + if (singleton == null) + singleton = new CacheFSInfo(); + context.put(FSInfo.class, singleton); + return singleton; + } + }); + } + + static CacheFSInfo singleton; + + public void clearCache() { + cache.clear(); + } + + @Override + public File getCanonicalFile(File file) { + Entry e = getEntry(file); + return e.canonicalFile; + } + + @Override + public boolean exists(File file) { + Entry e = getEntry(file); + return e.exists; + } + + @Override + public boolean isDirectory(File file) { + Entry e = getEntry(file); + return e.isDirectory; + } + + @Override + public boolean isFile(File file) { + Entry e = getEntry(file); + return e.isFile; + } + + @Override + public List getJarClassPath(File file) throws IOException { + // don't bother to lock the cache, because it is thread-safe, and + // because the worst that can happen would be to create two identical + // jar class paths together and have one overwrite the other. + Entry e = getEntry(file); + if (e.jarClassPath == null) + e.jarClassPath = super.getJarClassPath(file); + return e.jarClassPath; + } + + private Entry getEntry(File file) { + // don't bother to lock the cache, because it is thread-safe, and + // because the worst that can happen would be to create two identical + // entries together and have one overwrite the other. + Entry e = cache.get(file); + if (e == null) { + e = new Entry(); + e.canonicalFile = super.getCanonicalFile(file); + e.exists = super.exists(file); + e.isDirectory = super.isDirectory(file); + e.isFile = super.isFile(file); + cache.put(file, e); + } + return e; + } + + // could also be a Map> ? + private Map cache = new ConcurrentHashMap(); + + private static class Entry { + File canonicalFile; + boolean exists; + boolean isFile; + boolean isDirectory; + List jarClassPath; + } +} diff -r 3a05355982a9 -r 5072b0dd3d52 langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/FSInfo.java Wed Sep 03 10:46:25 2008 -0700 @@ -0,0 +1,89 @@ + +package com.sun.tools.javac.file; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.StringTokenizer; +import java.util.jar.Attributes; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +import com.sun.tools.javac.util.Context; + +/** + * Get meta-info about files. Default direct (non-caching) implementation. + * @see CacheFSInfo + */ +public class FSInfo { + + /** Get the FSInfo instance for this context. + * @param context the context + * @return the Paths instance for this context + */ + public static FSInfo instance(Context context) { + FSInfo instance = context.get(FSInfo.class); + if (instance == null) + instance = new FSInfo(); + return instance; + } + + protected FSInfo() { + } + + protected FSInfo(Context context) { + context.put(FSInfo.class, this); + } + + public File getCanonicalFile(File file) { + try { + return file.getCanonicalFile(); + } catch (IOException e) { + return file.getAbsoluteFile(); + } + } + + public boolean exists(File file) { + return file.exists(); + } + + public boolean isDirectory(File file) { + return file.isDirectory(); + } + + public boolean isFile(File file) { + return file.isFile(); + } + + public List getJarClassPath(File file) throws IOException { + String parent = file.getParent(); + JarFile jarFile = new JarFile(file); + try { + Manifest man = jarFile.getManifest(); + if (man == null) + return Collections.emptyList(); + + Attributes attr = man.getMainAttributes(); + if (attr == null) + return Collections.emptyList(); + + String path = attr.getValue(Attributes.Name.CLASS_PATH); + if (path == null) + return Collections.emptyList(); + + List list = new ArrayList(); + + for (StringTokenizer st = new StringTokenizer(path); st.hasMoreTokens(); ) { + String elt = st.nextToken(); + File f = (parent == null ? new File(elt) : new File(parent, elt)); + list.add(f); + } + + return list; + } finally { + jarFile.close(); + } + } +} diff -r 3a05355982a9 -r 5072b0dd3d52 langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java --- a/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Fri Aug 29 11:10:12 2008 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/JavacFileManager.java Wed Sep 03 10:46:25 2008 -0700 @@ -55,7 +55,6 @@ import java.util.Iterator; import java.util.Map; import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; import java.util.zip.ZipFile; import javax.lang.model.SourceVersion; @@ -88,10 +87,6 @@ boolean useZipFileIndex; - private static boolean CHECK_ZIP_TIMESTAMP = false; - private static Map isDirectory = new ConcurrentHashMap(); - - public static char[] toArray(CharBuffer buffer) { if (buffer.hasArray()) return ((CharBuffer)buffer.compact().flip()).array(); @@ -110,6 +105,8 @@ private Options options; + private FSInfo fsInfo; + private final File uninited = new File("U N I N I T E D"); private final Set sourceOrClass = @@ -172,9 +169,9 @@ } options = Options.instance(context); + fsInfo = FSInfo.instance(context); useZipFileIndex = System.getProperty("useJavaUtilZip") == null;// TODO: options.get("useJavaUtilZip") == null; - CHECK_ZIP_TIMESTAMP = System.getProperty("checkZipIndexTimestamp") != null;// TODO: options.get("checkZipIndexTimestamp") != null; mmappedIO = options.get("mmappedIO") != null; ignoreSymbolFile = options.get("ignore.symbol.file") != null; @@ -289,20 +286,7 @@ ListBuffer l) { Archive archive = archives.get(directory); - boolean isFile = false; - if (CHECK_ZIP_TIMESTAMP) { - Boolean isf = isDirectory.get(directory); - if (isf == null) { - isFile = directory.isFile(); - isDirectory.put(directory, isFile); - } - else { - isFile = directory.isFile(); - } - } - else { - isFile = directory.isFile(); - } + boolean isFile = fsInfo.isFile(directory); if (archive != null || isFile) { if (archive == null) { diff -r 3a05355982a9 -r 5072b0dd3d52 langtools/src/share/classes/com/sun/tools/javac/file/Paths.java --- a/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Fri Aug 29 11:10:12 2008 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/file/Paths.java Wed Sep 03 10:46:25 2008 -0700 @@ -31,19 +31,11 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; -import java.util.jar.JarFile; -import java.util.jar.Manifest; -import java.util.jar.Attributes; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Iterator; -import java.util.StringTokenizer; import java.util.zip.ZipFile; -import java.util.ArrayList; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; import javax.tools.JavaFileManager.Location; import com.sun.tools.javac.code.Lint; @@ -90,21 +82,8 @@ /** Handler for -Xlint options */ private Lint lint; - private static boolean NON_BATCH_MODE = System.getProperty("nonBatchMode") != null;// TODO: Use -XD compiler switch for this. - private static Map pathExistanceCache = new ConcurrentHashMap(); - private static Map> manifestEntries = new ConcurrentHashMap>(); - private static Map isDirectory = new ConcurrentHashMap(); - private static Lock lock = new ReentrantLock(); - - public static void clearPathExistanceCache() { - pathExistanceCache.clear(); - } - - static class PathEntry { - boolean exists = false; - boolean isFile = false; - File cannonicalPath = null; - } + /** Access to (possibly cached) file info */ + private FSInfo fsInfo; protected Paths(Context context) { context.put(pathsKey, this); @@ -116,6 +95,7 @@ log = Log.instance(context); options = Options.instance(context); lint = Lint.instance(context); + fsInfo = FSInfo.instance(context); } /** Whether to warn about non-existent path elements */ @@ -294,51 +274,17 @@ } public void addFile(File file, boolean warn) { - boolean foundInCache = false; - PathEntry pe = null; - if (!NON_BATCH_MODE) { - pe = pathExistanceCache.get(file); - if (pe != null) { - foundInCache = true; - } - else { - pe = new PathEntry(); - } - } - else { - pe = new PathEntry(); - } - - File canonFile; - try { - if (!foundInCache) { - pe.cannonicalPath = file.getCanonicalFile(); - } - else { - canonFile = pe.cannonicalPath; - } - } catch (IOException e) { - pe.cannonicalPath = canonFile = file; - } - - if (contains(file) || canonicalValues.contains(pe.cannonicalPath)) { + File canonFile = fsInfo.getCanonicalFile(file); + if (contains(file) || canonicalValues.contains(canonFile)) { /* Discard duplicates and avoid infinite recursion */ return; } - if (!foundInCache) { - pe.exists = file.exists(); - pe.isFile = file.isFile(); - if (!NON_BATCH_MODE) { - pathExistanceCache.put(file, pe); - } - } - - if (! pe.exists) { + if (! fsInfo.exists(file)) { /* No such file or directory exists */ if (warn) log.warning("path.element.not.found", file); - } else if (pe.isFile) { + } else if (fsInfo.isFile(file)) { /* File is an ordinary file. */ if (!isArchive(file)) { /* Not a recognized extension; open it to see if @@ -360,9 +306,9 @@ /* Now what we have left is either a directory or a file name confirming to archive naming convention */ super.add(file); - canonicalValues.add(pe.cannonicalPath); + canonicalValues.add(canonFile); - if (expandJarClassPaths && file.exists() && file.isFile()) + if (expandJarClassPaths && fsInfo.exists(file) && fsInfo.isFile(file)) addJarClassPath(file, warn); } @@ -372,58 +318,8 @@ // filenames, but if we do, we should redo all path-related code. private void addJarClassPath(File jarFile, boolean warn) { try { - java.util.List manifestsList = manifestEntries.get(jarFile); - if (!NON_BATCH_MODE) { - lock.lock(); - try { - if (manifestsList != null) { - for (File entr : manifestsList) { - addFile(entr, warn); - } - return; - } - } - finally { - lock.unlock(); - } - } - - if (!NON_BATCH_MODE) { - manifestsList = new ArrayList(); - manifestEntries.put(jarFile, manifestsList); - } - - String jarParent = jarFile.getParent(); - JarFile jar = new JarFile(jarFile); - - try { - Manifest man = jar.getManifest(); - if (man == null) return; - - Attributes attr = man.getMainAttributes(); - if (attr == null) return; - - String path = attr.getValue(Attributes.Name.CLASS_PATH); - if (path == null) return; - - for (StringTokenizer st = new StringTokenizer(path); - st.hasMoreTokens();) { - String elt = st.nextToken(); - File f = (jarParent == null ? new File(elt) : new File(jarParent, elt)); - addFile(f, warn); - - if (!NON_BATCH_MODE) { - lock.lock(); - try { - manifestsList.add(f); - } - finally { - lock.unlock(); - } - } - } - } finally { - jar.close(); + for (File f: fsInfo.getJarClassPath(jarFile)) { + addFile(f, warn); } } catch (IOException e) { log.error("error.reading.file", jarFile, e.getLocalizedMessage()); @@ -554,24 +450,9 @@ } /** Is this the name of an archive file? */ - private static boolean isArchive(File file) { + private boolean isArchive(File file) { String n = file.getName().toLowerCase(); - boolean isFile = false; - if (!NON_BATCH_MODE) { - Boolean isf = isDirectory.get(file); - if (isf == null) { - isFile = file.isFile(); - isDirectory.put(file, isFile); - } - else { - isFile = isf; - } - } - else { - isFile = file.isFile(); - } - - return isFile + return fsInfo.isFile(file) && (n.endsWith(".jar") || n.endsWith(".zip")); } } diff -r 3a05355982a9 -r 5072b0dd3d52 langtools/src/share/classes/com/sun/tools/javac/main/Main.java --- a/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Fri Aug 29 11:10:12 2008 -0700 +++ b/langtools/src/share/classes/com/sun/tools/javac/main/Main.java Wed Sep 03 10:46:25 2008 -0700 @@ -31,6 +31,7 @@ import java.util.MissingResourceException; import com.sun.tools.javac.code.Source; +import com.sun.tools.javac.file.CacheFSInfo; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.main.JavacOption.Option; @@ -368,6 +369,12 @@ context.put(Log.outKey, out); + // allow System property in following line as a Mustang legacy + boolean batchMode = (options.get("nonBatchMode") == null + && System.getProperty("nonBatchMode") == null); + if (batchMode) + CacheFSInfo.preRegister(context); + fileManager = context.get(JavaFileManager.class); comp = JavaCompiler.instance(context);