Speeding up jmod

Andrej Golovnin andrej.golovnin at gmail.com
Sun May 1 17:28:34 UTC 2016


Hi Chris, Alan,

I have updated my patch. Additionally to the other changes
it warps the InputStream returned by Files.newInputStream()
in a BufferedInputStream in the method
JmodFileWriter#processSection(ZipOutputStream, Section, Path)
because Files.newInputStream() returns an unbuffered InputStream
per specification.

Best regards,
Andrej Golovnin
-------------- next part --------------
diff -r 7210b5dbd92f src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java
--- a/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Sat Apr 30 16:41:08 2016 -0700
+++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/JmodTask.java	Sun May 01 19:09:04 2016 +0200
@@ -373,7 +373,6 @@
         final String osArch = options.osArch;
         final String osVersion = options.osVersion;
         final List<PathMatcher> excludes = options.excludes;
-        final Hasher hasher = hasher();
 
         JmodFileWriter() { }
 
@@ -400,31 +399,34 @@
          * on the class path of directories and JAR files.
          */
         Supplier<InputStream> newModuleInfoSupplier() throws IOException {
-            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            byte[] bytes = null;
             for (Path e: classpath) {
                 if (Files.isDirectory(e)) {
                     Path mi = e.resolve(MODULE_INFO);
                     if (Files.isRegularFile(mi)) {
-                        Files.copy(mi, baos);
+                        bytes = Files.readAllBytes(mi);
                         break;
                     }
                 } else if (Files.isRegularFile(e) && e.toString().endsWith(".jar")) {
                     try (JarFile jf = new JarFile(e.toFile())) {
                         ZipEntry entry = jf.getEntry(MODULE_INFO);
                         if (entry != null) {
-                            jf.getInputStream(entry).transferTo(baos);
-                            break;
+                            byte[] tmp = new byte[(int) entry.getSize()];
+                            if (jf.getInputStream(entry).read(tmp) == tmp.length) {
+                                bytes = tmp;
+                                break;
+                            }
                         }
                     } catch (ZipException x) {
                         // Skip. Do nothing. No packages will be added.
                     }
                 }
             }
-            if (baos.size() == 0) {
+            if (bytes == null) {
                 return null;
             } else {
-                byte[] bytes = baos.toByteArray();
-                return () -> new ByteArrayInputStream(bytes);
+                byte[] tmp = bytes;
+                return () -> new ByteArrayInputStream(tmp);
             }
         }
 
@@ -450,7 +452,6 @@
             try (InputStream in = miSupplier.get()) {
                 descriptor = ModuleDescriptor.read(in);
             }
-
             // copy the module-info.class into the jmod with the additional
             // attributes for the version, main class and other meta data
             try (InputStream in = miSupplier.get()) {
@@ -479,6 +480,7 @@
                 if (moduleVersion != null)
                     extender.version(moduleVersion);
 
+                Hasher hasher = hasher(descriptor);
                 if (hasher != null) {
                     ModuleHashes moduleHashes = hasher.computeHashes(descriptor.name());
                     if (moduleHashes != null) {
@@ -504,50 +506,36 @@
          * The jmod file is being created and does not exist in the
          * given modulepath.
          */
-        private Hasher hasher() {
+        private Hasher hasher(ModuleDescriptor descriptor) {
             if (options.modulesToHash == null)
                 return null;
 
-            try {
-                Supplier<InputStream> miSupplier = newModuleInfoSupplier();
-                if (miSupplier == null) {
-                    throw new IOException(MODULE_INFO + " not found");
+            URI uri = options.jmodFile.toUri();
+            ModuleReference mref = new ModuleReference(descriptor, uri, new Supplier<>() {
+                @Override
+                public ModuleReader get() {
+                    throw new UnsupportedOperationException();
                 }
+            });
 
-                ModuleDescriptor descriptor;
-                try (InputStream in = miSupplier.get()) {
-                    descriptor = ModuleDescriptor.read(in);
-                }
+            // compose a module finder with the module path and also
+            // a module finder that can find the jmod file being created
+            ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
+                new ModuleFinder() {
+                    @Override
+                    public Optional<ModuleReference> find(String name) {
+                        if (descriptor.name().equals(name))
+                            return Optional.of(mref);
+                        else return Optional.empty();
+                    }
 
-                URI uri = options.jmodFile.toUri();
-                ModuleReference mref = new ModuleReference(descriptor, uri, new Supplier<>() {
                     @Override
-                    public ModuleReader get() {
-                        throw new UnsupportedOperationException();
+                    public Set<ModuleReference> findAll() {
+                        return Collections.singleton(mref);
                     }
                 });
 
-                // compose a module finder with the module path and also
-                // a module finder that can find the jmod file being created
-                ModuleFinder finder = ModuleFinder.compose(options.moduleFinder,
-                    new ModuleFinder() {
-                        @Override
-                        public Optional<ModuleReference> find(String name) {
-                            if (descriptor.name().equals(name))
-                                return Optional.of(mref);
-                            else return Optional.empty();
-                        }
-
-                        @Override
-                        public Set<ModuleReference> findAll() {
-                            return Collections.singleton(mref);
-                        }
-                    });
-
-                return new Hasher(finder);
-            } catch (IOException e) {
-                throw new UncheckedIOException(e);
-            }
+            return new Hasher(finder);
         }
 
         /**
@@ -617,7 +605,7 @@
         String toPackageName(ZipEntry entry) {
             String name = entry.getName();
             assert name.endsWith(".class");
-            int index = name.lastIndexOf("/");
+            int index = name.lastIndexOf('/');
             if (index != -1)
                 return name.substring(0, index).replace('/', '.');
             else
@@ -665,7 +653,8 @@
                     Path relPath = top.relativize(file);
                     if (!relPath.toString().equals(MODULE_INFO)
                             && !matches(relPath, excludes)) {
-                        try (InputStream in = Files.newInputStream(file)) {
+                        try (InputStream in = new BufferedInputStream(
+                                Files.newInputStream(file))) {
                             writeZipEntry(zos, in, prefix, relPath.toString());
                         }
                     }
@@ -714,7 +703,7 @@
             public boolean test(JarEntry je) {
                 String name = je.getName();
                 // ## no support for excludes. Is it really needed?
-                return !name.endsWith(MODULE_INFO) && !je.isDirectory();
+                return !je.isDirectory() && !name.endsWith(MODULE_INFO);
             }
         }
     }


More information about the jigsaw-dev mailing list