# HG changeset patch # User sherman # Date 1229583037 28800 # Node ID 4659af392d07f98f42a095cc63bec0498c3d4243 # Parent f8b8bfa64fc1af094d571457dc078f84566c59c0 6496274: jar seems to use more CPU than it should Summary: boost jar creating performance especially for the large jar file Reviewed-by: martin diff -r f8b8bfa64fc1 -r 4659af392d07 jdk/src/share/classes/sun/tools/jar/Main.java --- a/jdk/src/share/classes/sun/tools/jar/Main.java Wed Dec 10 14:03:15 2008 -0800 +++ b/jdk/src/share/classes/sun/tools/jar/Main.java Wed Dec 17 22:50:37 2008 -0800 @@ -46,9 +46,18 @@ String zname = ""; String[] files; String rootjar = null; - Hashtable filesTable = new Hashtable(); - Vector paths = new Vector(); - Vector v; + + // An entryName(path)->File map generated during "expand", it helps to + // decide whether or not an existing entry in a jar file needs to be + // replaced, during the "update" operation. + Map entryMap = new HashMap(); + + // All files need to be added/updated. + Set entries = new LinkedHashSet(); + + // Directories specified by "-C" operation. + List paths = new ArrayList(); + CRC32 crc32 = new CRC32(); /* * cflag: create @@ -175,7 +184,8 @@ vflag = false; } } - create(new BufferedOutputStream(out), expand(files), manifest); + expand(null, files, false); + create(new BufferedOutputStream(out, 4096), manifest); if (in != null) { in.close(); } @@ -198,8 +208,8 @@ } InputStream manifest = (!Mflag && (mname != null)) ? (new FileInputStream(mname)) : null; - expand(files); - boolean updateOk = update(in, new BufferedOutputStream(out), manifest); + expand(null, files, true); + boolean updateOk = update(in, new BufferedOutputStream(out), manifest, null); if (ok) { ok = updateOk; } @@ -354,7 +364,7 @@ while (dir.indexOf("//") > -1) { dir = dir.replace("//", "/"); } - paths.addElement(dir.replace(File.separatorChar, '/')); + paths.add(dir.replace(File.separatorChar, '/')); nameBuf[k++] = dir + args[++i]; } else { nameBuf[k++] = args[i]; @@ -387,17 +397,7 @@ * Expands list of files to process into full list of all files that * can be found by recursively descending directories. */ - String[] expand(String[] files) { - v = new Vector(); - expand(null, files, v, filesTable); - files = new String[v.size()]; - for (int i = 0; i < files.length; i++) { - files[i] = ((File)v.elementAt(i)).getPath(); - } - return files; - } - - void expand(File dir, String[] files, Vector v, Hashtable t) { + void expand(File dir, String[] files, boolean isUpdate) { if (files == null) { return; } @@ -409,17 +409,20 @@ f = new File(dir, files[i]); } if (f.isFile()) { - if (!t.contains(f)) { - t.put(entryName(f.getPath()), f); - v.addElement(f); + if (entries.add(f)) { + if (isUpdate) + entryMap.put(entryName(f.getPath()), f); } } else if (f.isDirectory()) { - String dirPath = f.getPath(); - dirPath = (dirPath.endsWith(File.separator)) ? dirPath : - (dirPath + File.separator); - t.put(entryName(dirPath), f); - v.addElement(f); - expand(f, f.list(), v, t); + if (entries.add(f)) { + if (isUpdate) { + String dirPath = f.getPath(); + dirPath = (dirPath.endsWith(File.separator)) ? dirPath : + (dirPath + File.separator); + entryMap.put(entryName(dirPath), f); + } + expand(f, f.list(), isUpdate); + } } else { error(formatMsg("error.nosuch.fileordir", String.valueOf(f))); ok = false; @@ -430,7 +433,7 @@ /* * Creates a new JAR file. */ - void create(OutputStream out, String[] files, Manifest manifest) + void create(OutputStream out, Manifest manifest) throws IOException { ZipOutputStream zos = new JarOutputStream(out); @@ -455,8 +458,8 @@ manifest.write(zos); zos.closeEntry(); } - for (int i = 0; i < files.length; i++) { - addFile(zos, new File(files[i])); + for (File file: entries) { + addFile(zos, file); } zos.close(); } @@ -465,10 +468,9 @@ * update an existing jar file. */ boolean update(InputStream in, OutputStream out, - InputStream newManifest) throws IOException + InputStream newManifest, + JarIndex jarIndex) throws IOException { - Hashtable t = filesTable; - Vector v = this.v; ZipInputStream zis = new ZipInputStream(in); ZipOutputStream zos = new JarOutputStream(out); ZipEntry e = null; @@ -477,8 +479,8 @@ int n = 0; boolean updateOk = true; - if (t.containsKey(INDEX)) { - addIndex((JarIndex)t.get(INDEX), zos); + if (jarIndex != null) { + addIndex(jarIndex, zos); } // put the old entries first, replace if necessary @@ -488,9 +490,8 @@ boolean isManifestEntry = name.toUpperCase( java.util.Locale.ENGLISH). equals(MANIFEST); - if ((name.toUpperCase().equals(INDEX) - && t.containsKey(INDEX)) - || (Mflag && isManifestEntry)) { + if ((name.toUpperCase().equals(INDEX) && jarIndex != null) + || (Mflag && isManifestEntry)) { continue; } else if (isManifestEntry && ((newManifest != null) || (ename != null))) { @@ -514,8 +515,7 @@ } updateManifest(old, zos); } else { - if (!t.containsKey(name)) { // copy the old stuff - + if (!entryMap.containsKey(name)) { // copy the old stuff // do our own compression ZipEntry e2 = new ZipEntry(name); e2.setMethod(e.getMethod()); @@ -531,21 +531,17 @@ zos.write(buf, 0, n); } } else { // replace with the new files - addFile(zos, (File)(t.get(name))); - t.remove(name); + File f = entryMap.get(name); + addFile(zos, f); + entryMap.remove(name); + entries.remove(f); } } } - t.remove(INDEX); // add the remaining new files - if (!t.isEmpty()) { - for (int i = 0; i < v.size(); i++) { - File f = (File)v.elementAt(i); - if (t.containsValue(f)) { - addFile(zos, f); - } - } + for (File f: entries) { + addFile(zos, f); } if (!foundManifest) { if (newManifest != null) { @@ -611,8 +607,7 @@ private String entryName(String name) { name = name.replace(File.separatorChar, '/'); String matchPath = ""; - for (int i = 0; i < paths.size(); i++) { - String path = (String)paths.elementAt(i); + for (String path : paths) { if (name.startsWith(path) && (path.length() > matchPath.length())) { matchPath = path; } @@ -669,7 +664,6 @@ void addFile(ZipOutputStream zos, File file) throws IOException { String name = file.getPath(); boolean isDir = file.isDirectory(); - if (isDir) { name = name.endsWith(File.separator) ? name : (name + File.separator); @@ -704,7 +698,7 @@ } zos.putNextEntry(e); if (!isDir) { - byte[] buf = new byte[1024]; + byte[] buf = new byte[8192]; int len; InputStream is = new BufferedInputStream(new FileInputStream(file)); while ((len = is.read(buf, 0, buf.length)) != -1) { @@ -749,7 +743,7 @@ */ private void crc32File(ZipEntry e, File f) throws IOException { InputStream is = new BufferedInputStream(new FileInputStream(f)); - byte[] buf = new byte[1024]; + byte[] buf = new byte[8192]; crc32.reset(); int r = 0; int nread = 0; @@ -772,7 +766,7 @@ void extract(InputStream in, String files[]) throws IOException { ZipInputStream zis = new ZipInputStream(in); ZipEntry e; - // Set of all directory entries specified in archive. Dissallows + // Set of all directory entries specified in archive. Disallows // null entries. Disallows all entries if using pre-6.0 behavior. Set dirs = new HashSet() { public boolean add(ZipEntry e) { @@ -897,17 +891,16 @@ } } - /** * Output the class index table to the INDEX.LIST file of the * root jar file. */ void dumpIndex(String rootjar, JarIndex index) throws IOException { - filesTable.put(INDEX, index); File scratchFile = File.createTempFile("scratch", null, new File(".")); File jarFile = new File(rootjar); boolean updateOk = update(new FileInputStream(jarFile), - new FileOutputStream(scratchFile), null); + new FileOutputStream(scratchFile), + null, index); jarFile.delete(); if (!scratchFile.renameTo(jarFile)) { scratchFile.delete();