8147794: Jlink's ModuleEntry.stream can't be consumed more than once and ModuleEntry content should be read only if needed
authorsundar
Fri, 24 Jun 2016 19:56:50 +0530
changeset 39151 34455cc82f5e
parent 39150 cb99396625b4
child 39152 ab6a58b6301d
8147794: Jlink's ModuleEntry.stream can't be consumed more than once and ModuleEntry content should be read only if needed Reviewed-by: jlaskey, psandoz
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryImpl.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java
jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java
jdk/test/tools/jlink/ImageFilePoolTest.java
jdk/test/tools/jlink/ResourcePoolTest.java
jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java
jdk/test/tools/jlink/plugins/ExcludePluginTest.java
jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java
jdk/test/tools/jlink/plugins/StringSharingPluginTest.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/AbstractModuleEntry.java	Fri Jun 24 19:56:50 2016 +0530
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.InputStream;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ModuleEntry;
+
+/**
+ * A LinkModuleEntry is the elementary unit of data inside an image. It is
+ * generally a file. e.g.: a java class file, a resource file, a shared library,
+ * ...
+ * <br>
+ * A LinkModuleEntry is identified by a path of the form:
+ * <ul>
+ * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
+ * name}</li>
+ * <li>For other files (shared lib, launchers, config, ...):/{module name}/
+ * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
+ * </ul>
+ */
+abstract class AbstractModuleEntry implements ModuleEntry {
+    private final String path;
+    private final String module;
+    private final Type type;
+
+    /**
+     * Create a new AbstractModuleEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param type The data type.
+     */
+    AbstractModuleEntry(String module, String path, Type type) {
+        this.module = Objects.requireNonNull(module);
+        this.path = Objects.requireNonNull(path);
+        this.type = Objects.requireNonNull(type);
+    }
+
+    @Override
+    public final String getModule() {
+        return module;
+    }
+
+    @Override
+    public final String getPath() {
+        return path;
+    }
+
+    @Override
+    public final Type getType() {
+        return type;
+    }
+
+    @Override
+    public int hashCode() {
+        int hash = 7;
+        hash = 89 * hash + Objects.hashCode(this.path);
+        return hash;
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (!(other instanceof AbstractModuleEntry)) {
+            return false;
+        }
+        AbstractModuleEntry f = (AbstractModuleEntry) other;
+        return f.path.equals(path);
+    }
+
+    @Override
+    public String toString() {
+        return getPath();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ArchiveEntryModuleEntry.java	Fri Jun 24 19:56:50 2016 +0530
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ModuleEntry;
+
+/**
+ * A ModuleEntry backed by a given Archive Entry.
+ */
+final class ArchiveEntryModuleEntry extends AbstractModuleEntry {
+    private final Archive.Entry entry;
+
+    /**
+     * Create a new ArchiveModuleEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param entry The archive Entry.
+     */
+    ArchiveEntryModuleEntry(String module, String path, Archive.Entry entry) {
+        super(module, path, getImageFileType(entry));
+        this.entry = entry;
+    }
+
+    @Override
+    public InputStream stream() {
+        try {
+            return entry.stream();
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public long getLength() {
+        return entry.size();
+    }
+
+    private static ModuleEntry.Type getImageFileType(Archive.Entry entry) {
+        Objects.requireNonNull(entry);
+        switch(entry.type()) {
+            case CLASS_OR_RESOURCE:
+                return ModuleEntry.Type.CLASS_OR_RESOURCE;
+            case CONFIG:
+                return ModuleEntry.Type.CONFIG;
+            case NATIVE_CMD:
+                return ModuleEntry.Type.NATIVE_CMD;
+            case NATIVE_LIB:
+                return ModuleEntry.Type.NATIVE_LIB;
+            default:
+                return ModuleEntry.Type.OTHER;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ByteArrayModuleEntry.java	Fri Jun 24 19:56:50 2016 +0530
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ModuleEntry;
+
+/**
+ * A ModuleEntry backed by a given byte[].
+ */
+class ByteArrayModuleEntry extends AbstractModuleEntry {
+    private final byte[] buffer;
+
+    /**
+     * Create a new ByteArrayModuleEntry.
+     *
+     * @param module The module name.
+     * @param path The data path identifier.
+     * @param type The data type.
+     * @param buf  The byte buffer.
+     */
+    ByteArrayModuleEntry(String module, String path, Type type, byte[] buffer) {
+        super(module, path, type);
+        this.buffer = Objects.requireNonNull(buffer);
+    }
+
+    @Override
+    public byte[] getBytes() {
+        return buffer.clone();
+    }
+
+    @Override
+    public InputStream stream() {
+        return new ByteArrayInputStream(buffer);
+    }
+
+    @Override
+    public void write(OutputStream out) {
+        try {
+            out.write(buffer);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public long getLength() {
+        return buffer.length;
+    }
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImageFileCreator.java	Fri Jun 24 19:56:50 2016 +0530
@@ -233,8 +233,7 @@
 
         // write module content
         for (ModuleEntry res : content) {
-            byte[] buf = res.getBytes();
-            out.write(buf, 0, buf.length);
+            res.write(out);
         }
 
         tree.addContent(out);
@@ -244,21 +243,6 @@
         return resultResources;
     }
 
-    private static ModuleEntry.Type mapImageFileType(EntryType type) {
-        switch(type) {
-            case CONFIG: {
-                return ModuleEntry.Type.CONFIG;
-            }
-            case NATIVE_CMD: {
-                return ModuleEntry.Type.NATIVE_CMD;
-            }
-            case NATIVE_LIB: {
-                return ModuleEntry.Type.NATIVE_LIB;
-            }
-        }
-        return null;
-    }
-
     private static ModulePoolImpl createPools(Set<Archive> archives,
             Map<String, List<Entry>> entriesForModule,
             ByteOrder byteOrder,
@@ -278,34 +262,22 @@
         for (Archive archive : archives) {
             String mn = archive.moduleName();
             for (Entry entry : entriesForModule.get(mn)) {
-
+                String path;
                 if (entry.type() == EntryType.CLASS_OR_RESOURCE) {
                     // Removal of "classes/" radical.
-                    String path = entry.name();
-                    try (InputStream stream = entry.stream()) {
-                        byte[] bytes = readAllBytes(stream);
-                        if (path.endsWith("module-info.class")) {
-                            path = "/" + path;
-                        } else {
-                            path = "/" + mn + "/" + path;
-                        }
-                        try {
-                            resources.add(ModuleEntry.create(path, bytes));
-                        } catch (Exception ex) {
-                            throw new IOException(ex);
-                        }
+                    path = entry.name();
+                    if (path.endsWith("module-info.class")) {
+                        path = "/" + path;
+                    } else {
+                        path = "/" + mn + "/" + path;
                     }
                 } else {
-                    try {
-                        // Entry.path() contains the kind of file native, conf, bin, ...
-                        // Keep it to avoid naming conflict (eg: native/jvm.cfg and config/jvm.cfg
-                        resources.add(ModuleEntry.create(mn,
-                                "/" + mn + "/" + entry.path(), mapImageFileType(entry.type()),
-                                entry.stream(), entry.size()));
-                    } catch (Exception ex) {
-                        throw new IOException(ex);
-                    }
+                    // Entry.path() contains the kind of file native, conf, bin, ...
+                    // Keep it to avoid naming conflict (eg: native/jvm.cfg and config/jvm.cfg
+                    path = "/" + mn + "/" + entry.path();
                 }
+
+                resources.add(new ArchiveEntryModuleEntry(mn, path, entry));
             }
         }
         return resources;
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ImagePluginStack.java	Fri Jun 24 19:56:50 2016 +0530
@@ -443,9 +443,7 @@
                         byte[] bytes = decompressor.decompressResource(getByteOrder(),
                                 (int offset) -> pool.getStringTable().getString(offset),
                                 res.getBytes());
-                        res = ModuleEntry.create(res.getPath(),
-                                new ByteArrayInputStream(bytes),
-                                bytes.length);
+                        res = res.create(bytes);
                     } catch (IOException ex) {
                         throw new PluginException(ex);
                     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryFactory.java	Fri Jun 24 19:56:50 2016 +0530
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jdk.tools.jlink.internal;
+
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ModuleEntry;
+
+public final class ModuleEntryFactory {
+    private ModuleEntryFactory() {}
+
+    public static ModuleEntry create(String path,
+            ModuleEntry.Type type, byte[] content) {
+        return new ByteArrayModuleEntry(moduleFrom(path), path, type, content);
+    }
+
+    public static ModuleEntry create(String path,
+            ModuleEntry.Type type, Path file) {
+        return new PathModuleEntry(moduleFrom(path), path, type, file);
+    }
+
+    public static ModuleEntry create(ModuleEntry original, byte[] content) {
+        return new ByteArrayModuleEntry(original.getModule(),
+                original.getPath(), original.getType(), content);
+    }
+
+    public static ModuleEntry create(ModuleEntry original, Path file) {
+        return new PathModuleEntry(original.getModule(),
+                original.getPath(), original.getType(), file);
+    }
+
+    private static String moduleFrom(String path) {
+        Objects.requireNonNull(path);
+        if (path.isEmpty() || path.charAt(0) != '/') {
+            throw new IllegalArgumentException(path + " must start with /");
+        }
+        String noRoot = path.substring(1);
+        int idx = noRoot.indexOf('/');
+        if (idx == -1) {
+            throw new IllegalArgumentException("/ missing after module: " + path);
+        }
+        return noRoot.substring(0, idx);
+    }
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModuleEntryImpl.java	Fri Jun 24 11:20:24 2016 -0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. 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.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package jdk.tools.jlink.internal;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UncheckedIOException;
-import java.util.Objects;
-import jdk.tools.jlink.plugin.ModuleEntry;
-
-/**
- * A LinkModuleEntry is the elementary unit of data inside an image. It is
- * generally a file. e.g.: a java class file, a resource file, a shared library,
- * ...
- * <br>
- * A LinkModuleEntry is identified by a path of the form:
- * <ul>
- * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
- * name}</li>
- * <li>For other files (shared lib, launchers, config, ...):/{module name}/
- * {@literal bin|conf|native}/{dir1}>/.../{dirN}/{file name}</li>
- * </ul>
- */
-public class ModuleEntryImpl implements ModuleEntry {
-
-    private final Type type;
-    private final String path;
-    private final String module;
-    private final long length;
-    private final InputStream stream;
-    private byte[] buffer;
-
-    /**
-     * Create a new LinkModuleEntry.
-     *
-     * @param module The module name.
-     * @param path The data path identifier.
-     * @param type The data type.
-     * @param stream The data content stream.
-     * @param length The stream length.
-     */
-    public ModuleEntryImpl(String module, String path, Type type, InputStream stream, long length) {
-        Objects.requireNonNull(module);
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(type);
-        Objects.requireNonNull(stream);
-        this.path = path;
-        this.type = type;
-        this.module = module;
-        this.stream = stream;
-        this.length = length;
-    }
-
-    /**
-     * The LinkModuleEntry module name.
-     *
-     * @return The module name.
-     */
-    @Override
-    public final String getModule() {
-        return module;
-    }
-
-    /**
-     * The LinkModuleEntry path.
-     *
-     * @return The module path.
-     */
-    @Override
-    public final String getPath() {
-        return path;
-    }
-
-    /**
-     * The LinkModuleEntry's type.
-     *
-     * @return The data type.
-     */
-    @Override
-    public final Type getType() {
-        return type;
-    }
-
-    /**
-     * The LinkModuleEntry content as an array of byte.
-     *
-     * @return An Array of bytes.
-     */
-    @Override
-    public byte[] getBytes() {
-        if (buffer == null) {
-            try (InputStream is = stream) {
-                buffer = is.readAllBytes();
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-        return buffer;
-    }
-
-    /**
-     * The LinkModuleEntry content length.
-     *
-     * @return The length.
-     */
-    @Override
-    public long getLength() {
-        return length;
-    }
-
-    /**
-     * The LinkModuleEntry stream.
-     *
-     * @return The module data stream.
-     */
-    @Override
-    public InputStream stream() {
-        return stream;
-    }
-
-    @Override
-    public int hashCode() {
-        int hash = 7;
-        hash = 89 * hash + Objects.hashCode(this.path);
-        return hash;
-    }
-
-    @Override
-    public boolean equals(Object other) {
-        if (!(other instanceof ModuleEntryImpl)) {
-            return false;
-        }
-        ModuleEntryImpl f = (ModuleEntryImpl) other;
-        return f.path.equals(path);
-    }
-
-    @Override
-    public String toString() {
-        return getPath();
-    }
-}
\ No newline at end of file
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/ModulePoolImpl.java	Fri Jun 24 19:56:50 2016 +0530
@@ -95,7 +95,7 @@
         @Override
         public void add(ModuleEntry data) {
             if (isReadOnly()) {
-                throw new PluginException("LinkConfiguration is readonly");
+                throw new PluginException("ModulePool is readonly");
             }
             Objects.requireNonNull(data);
             if (!data.getModule().equals(name)) {
@@ -180,7 +180,7 @@
     @Override
     public void add(ModuleEntry data) {
         if (isReadOnly()) {
-            throw new PluginException("LinkConfiguration is readonly");
+            throw new PluginException("ModulePool is readonly");
         }
         Objects.requireNonNull(data);
         if (resources.get(data.getPath()) != null) {
@@ -215,7 +215,7 @@
     }
 
     /**
-     * The stream of modules contained in this LinkConfiguration.
+     * The stream of modules contained in this ModulePool.
      *
      * @return The stream of modules.
      */
@@ -225,7 +225,7 @@
     }
 
     /**
-     * Return the number of LinkModule count in this LinkConfiguration.
+     * Return the number of LinkModule count in this ModulePool.
      *
      * @return the module count.
      */
@@ -235,7 +235,7 @@
     }
 
     /**
-     * Get all ModuleEntry contained in this LinkConfiguration instance.
+     * Get all ModuleEntry contained in this ModulePool instance.
      *
      * @return The stream of LinkModuleEntries.
      */
@@ -245,7 +245,7 @@
     }
 
     /**
-     * Return the number of ModuleEntry count in this LinkConfiguration.
+     * Return the number of ModuleEntry count in this ModulePool.
      *
      * @return the entry count.
      */
@@ -267,7 +267,7 @@
     }
 
     /**
-     * Check if the LinkConfiguration contains the given ModuleEntry.
+     * Check if the ModulePool contains the given ModuleEntry.
      *
      * @param data The module data to check existence for.
      * @return The module data or null if not found.
@@ -279,7 +279,7 @@
     }
 
     /**
-     * Check if the LinkConfiguration contains some content at all.
+     * Check if the ModulePool contains some content at all.
      *
      * @return True, no content, false otherwise.
      */
@@ -289,16 +289,16 @@
     }
 
     /**
-     * Visit each ModuleEntry in this LinkConfiguration to transform it and
-     * copy the transformed ModuleEntry to the output LinkConfiguration.
+     * Visit each ModuleEntry in this ModulePool to transform it and
+     * copy the transformed ModuleEntry to the output ModulePool.
      *
      * @param transform The function called for each ModuleEntry found in
-     * the LinkConfiguration. The transform function should return a
+     * the ModulePool. The transform function should return a
      * ModuleEntry instance which will be added to the output or it should
      * return null if the passed ModuleEntry is to be ignored for the
      * output.
      *
-     * @param output The LinkConfiguration to be filled with Visitor returned
+     * @param output The ModulePool to be filled with Visitor returned
      * ModuleEntry.
      */
     @Override
@@ -351,14 +351,13 @@
     /**
      * A resource that has been compressed.
      */
-    public static final class CompressedModuleData extends ModuleEntryImpl {
+    public static final class CompressedModuleData extends ByteArrayModuleEntry {
 
         final long uncompressed_size;
 
         private CompressedModuleData(String module, String path,
-                InputStream stream, long size,
-                long uncompressed_size) {
-            super(module, path, ModuleEntry.Type.CLASS_OR_RESOURCE, stream, size);
+                byte[] content, long uncompressed_size) {
+            super(module, path, ModuleEntry.Type.CLASS_OR_RESOURCE, content);
             this.uncompressed_size = uncompressed_size;
         }
 
@@ -413,8 +412,7 @@
 
         CompressedModuleData compressedResource
                 = new CompressedModuleData(original.getModule(), original.getPath(),
-                        new ByteArrayInputStream(contentWithHeader),
-                        contentWithHeader.length, uncompressed_size);
+                        contentWithHeader, uncompressed_size);
         return compressedResource;
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/PathModuleEntry.java	Fri Jun 24 19:56:50 2016 +0530
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. 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.  Oracle designates this
+ * particular file as subject to the "Classfile" exception as provided
+ * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package jdk.tools.jlink.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Objects;
+import jdk.tools.jlink.plugin.ModuleEntry;
+
+/**
+ * A ModuleEntry backed by a given nio Path.
+ */
+public class PathModuleEntry extends AbstractModuleEntry {
+    private final Path file;
+
+    /**
+     * Create a new PathModuleEntry.
+     *
+     * @param module The module name.
+     * @param file The data file identifier.
+     * @param type The data type.
+     * @param file The Path for the resource content.
+     */
+    public PathModuleEntry(String module, String path, Type type, Path file) {
+        super(module, path, type);
+        this.file = Objects.requireNonNull(file);
+        if (!Files.isRegularFile(file)) {
+            throw new IllegalArgumentException(file + " not a file");
+        }
+    }
+
+    @Override
+    public final InputStream stream() {
+        try {
+            return Files.newInputStream(file);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+
+    @Override
+    public final long getLength() {
+        try {
+            return Files.size(file);
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
+}
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ExcludeVMPlugin.java	Fri Jun 24 19:56:50 2016 +0530
@@ -244,10 +244,7 @@
 
         byte[] content = builder.toString().getBytes(StandardCharsets.UTF_8);
 
-        return ModuleEntry.create(orig.getModule(),
-                orig.getPath(),
-                orig.getType(),
-                new ByteArrayInputStream(content), content.length);
+        return orig.create(content);
     }
 
     private static String jvmlib() {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/FileCopierPlugin.java	Fri Jun 24 19:56:50 2016 +0530
@@ -39,7 +39,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import jdk.tools.jlink.internal.ModuleEntryImpl;
+import jdk.tools.jlink.internal.PathModuleEntry;
 import jdk.tools.jlink.plugin.PluginException;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
@@ -66,13 +66,13 @@
     /**
      * Symbolic link to another path.
      */
-    public static abstract class SymImageFile extends ModuleEntryImpl {
+    public static abstract class SymImageFile extends PathModuleEntry {
 
         private final String targetPath;
 
         public SymImageFile(String targetPath, String module, String path,
-                ModuleEntry.Type type, InputStream stream, long size) {
-            super(module, path, type, stream, size);
+                ModuleEntry.Type type, Path file) {
+            super(module, path, type, file);
             this.targetPath = targetPath;
         }
 
@@ -85,23 +85,7 @@
 
         public SymImageFileImpl(String targetPath, Path file, String module,
                 String path, ModuleEntry.Type type) {
-            super(targetPath, module, path, type, newStream(file), length(file));
-        }
-    }
-
-    private static long length(Path file) {
-        try {
-            return Files.size(file);
-        } catch (IOException ex) {
-            throw new RuntimeException(ex);
-        }
-    }
-
-    private static InputStream newStream(Path file) {
-        try {
-            return Files.newInputStream(file);
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
+            super(targetPath, module, path, type, file);
         }
     }
 
@@ -175,9 +159,9 @@
         Objects.requireNonNull(pool);
         Objects.requireNonNull(file);
         Objects.requireNonNull(path);
-        ModuleEntry impl = ModuleEntry.create(FAKE_MODULE,
+        ModuleEntry impl = ModuleEntry.create(
                 "/" + FAKE_MODULE + "/other/" + path,
-                ModuleEntry.Type.OTHER, newStream(file), length(file));
+                ModuleEntry.Type.OTHER, file);
         try {
             pool.add(impl);
         } catch (Exception ex) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin.java	Fri Jun 24 19:56:50 2016 +0530
@@ -171,10 +171,9 @@
             byte[] bytes = result.getValue();
 
             // Add class to pool
-            ModuleEntry ndata = ModuleEntry.create(data.getModule(),
+            ModuleEntry ndata = ModuleEntry.create(
                     "/java.base/" + className + ".class",
-                    ModuleEntry.Type.CLASS_OR_RESOURCE,
-                    new ByteArrayInputStream(bytes), bytes.length);
+                    bytes);
             if (!out.contains(ndata)) {
                 out.add(ndata);
             }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin.java	Fri Jun 24 19:56:50 2016 +0530
@@ -123,9 +123,7 @@
                     if (Arrays.stream(cr.getInterfaces())
                         .anyMatch(i -> i.contains(METAINFONAME)) &&
                         stripUnsupportedLocales(bytes, cr)) {
-                        resource = ModuleEntry.create(MODULENAME, path,
-                            resource.getType(),
-                            new ByteArrayInputStream(bytes), bytes.length);
+                        resource = resource.create(bytes);
                     }
                 }
             }
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/StripDebugPlugin.java	Fri Jun 24 19:56:50 2016 +0530
@@ -75,7 +75,7 @@
                         ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
                         reader.accept(writer, ClassReader.SKIP_DEBUG);
                         byte[] content = writer.toByteArray();
-                        res = ModuleEntry.create(path, new ByteArrayInputStream(content), content.length);
+                        res = resource.create(content);
                     }
                 }
             } else if (predicate.test(res.getPath())) {
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/SystemModuleDescriptorPlugin.java	Fri Jun 24 19:56:50 2016 +0530
@@ -139,11 +139,7 @@
                     ModuleInfoRewriter minfoWriter =
                         new ModuleInfoRewriter(bain, mbuilder.conceals());
                     // replace with the overridden version
-                    data = ModuleEntry.create(data.getModule(),
-                                               data.getPath(),
-                                               data.getType(),
-                                               minfoWriter.stream(),
-                                               minfoWriter.size());
+                    data = data.create(minfoWriter.getBytes());
                 }
                 out.add(data);
             } catch (IOException e) {
@@ -158,12 +154,7 @@
                 return;
             if (builder.isOverriddenClass(data.getPath())) {
                 byte[] bytes = cwriter.toByteArray();
-                ModuleEntry ndata =
-                    ModuleEntry.create(data.getModule(),
-                                        data.getPath(),
-                                        data.getType(),
-                                        new ByteArrayInputStream(bytes),
-                                        bytes.length);
+                ModuleEntry ndata = data.create(bytes);
                 out.add(ndata);
             } else {
                 out.add(data);
@@ -183,8 +174,8 @@
             this.extender.write(this);
         }
 
-        InputStream stream() {
-            return new ByteArrayInputStream(buf);
+        byte[] getBytes() {
+            return buf;
         }
     }
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java	Fri Jun 24 19:56:50 2016 +0530
@@ -93,8 +93,7 @@
             }
 
             byte[] content = writer.toByteArray();
-            ModuleEntry res = ModuleEntry.create(path,
-                    new ByteArrayInputStream(content), content.length);
+            ModuleEntry res = ModuleEntry.create(path, content);
             transformedClasses.put(className, res);
         }
 
--- a/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/plugin/ModuleEntry.java	Fri Jun 24 19:56:50 2016 +0530
@@ -26,16 +26,18 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
-import java.util.Objects;
-import jdk.tools.jlink.internal.ImageFileCreator;
-import jdk.tools.jlink.internal.ModuleEntryImpl;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UncheckedIOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import jdk.tools.jlink.internal.ModuleEntryFactory;
 
 /**
- * A LinkModuleEntry is the elementary unit of data inside an image. It is
- * generally a file. e.g.: a java class file, a resource file, a shared library,
- * ...
+ * A ModuleEntry is the elementary unit of data inside an image. It is
+ * generally a file. e.g.: a java class file, a resource file, a shared library.
  * <br>
- * A LinkModuleEntry is identified by a path of the form:
+ * A ModuleEntry is identified by a path of the form:
  * <ul>
  * <li>For jimage content: /{module name}/{package1}/.../{packageN}/{file
  * name}</li>
@@ -63,93 +65,133 @@
         OTHER
     }
     /**
-     * The LinkModuleEntry module name.
+     * The ModuleEntry module name.
      *
      * @return The module name.
      */
     public String getModule();
 
     /**
-     * The LinkModuleEntry path.
+     * The ModuleEntry path.
      *
      * @return The module path.
      */
     public String getPath();
 
     /**
-     * The LinkModuleEntry's type.
+     * The ModuleEntry's type.
      *
      * @return The data type.
      */
     public Type getType();
 
     /**
-     * The LinkModuleEntry content as an array of byte.
+     * The ModuleEntry content as an array of bytes.
      *
      * @return An Array of bytes.
      */
-    public byte[] getBytes();
+    public default byte[] getBytes() {
+        try (InputStream is = stream()) {
+            return is.readAllBytes();
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
 
     /**
-     * The LinkModuleEntry content length.
+     * The ModuleEntry content length.
      *
      * @return The length.
      */
     public long getLength();
 
     /**
-     * The LinkModuleEntry stream.
+     * The ModuleEntry stream.
      *
      * @return The module data stream.
      */
     public InputStream stream();
 
+    /**
+     * Write the content of this ModuleEntry to stream.
+     *
+     * @param out the output stream
+     */
+    public default void write(OutputStream out) {
+        try {
+            out.write(getBytes());
+        } catch (IOException ex) {
+            throw new UncheckedIOException(ex);
+        }
+    }
 
     /**
-     * Create a LinkModuleEntry located inside a jimage file. Such
-     * LinkModuleEntry has a Type being equals to CLASS_OR_RESOURCE.
+     * Create a ModuleEntry with new content but other information
+     * copied from this ModuleEntry.
      *
-     * @param path The complete resource path (contains the module radical).
-     * @param content The resource content.
-     * @param size The content size.
-     * @return A new LinkModuleEntry.
+     * @param content The new resource content.
+     * @return A new ModuleEntry.
      */
-    public static ModuleEntry create(String path, InputStream content, long size) {
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(content);
-        String[] split = ImageFileCreator.splitPath(path);
-        String module = split[0];
-        return new ModuleEntryImpl(module, path, Type.CLASS_OR_RESOURCE, content, size);
+    public default ModuleEntry create(byte[] content) {
+        return ModuleEntryFactory.create(this, content);
     }
 
     /**
-     * Create a LinkModuleEntry for a file that will be located inside a jimage
-     * file.
+     * Create a ModuleEntry with new content but other information
+     * copied from this ModuleEntry.
+     *
+     * @param file The new resource content.
+     * @return A new ModuleEntry.
+     */
+    public default ModuleEntry create(Path file) {
+        return ModuleEntryFactory.create(this, file);
+    }
+
+    /**
+     * Create a ModuleEntry for a resource of the given type.
+     *
+     * @param path The resource path.
+     * @param type The ModuleEntry type.
+     * @param content The resource content.
+     * @return A new ModuleEntry.
+     */
+    public static ModuleEntry create(String path,
+            ModuleEntry.Type type, byte[] content) {
+        return ModuleEntryFactory.create(path, type, content);
+    }
+
+    /**
+     * Create a ModuleEntry for a resource of type {@link Type#CLASS_OR_RESOURCE}.
      *
      * @param path The resource path.
      * @param content The resource content.
-     * @return A new LinkModuleEntry.
+     * @return A new ModuleEntry.
      */
     public static ModuleEntry create(String path, byte[] content) {
-        return create(path, new ByteArrayInputStream(content),
-                content.length);
+        return create(path, Type.CLASS_OR_RESOURCE, content);
     }
 
     /**
-     * Create a LinkModuleEntry for a file that will be located outside a jimage
-     * file.
+     * Create a ModuleEntry for a resource of the given type.
      *
-     * @param module The module in which this files is located.
-     * @param path The file path locator (doesn't contain the module name).
-     * @param type The LinkModuleEntry type.
-     * @param content The file content.
-     * @param size The content size.
-     * @return A new LinkModuleEntry.
+     * @param path The resource path.
+     * @param type The ModuleEntry type.
+     * @param file The resource file.
+     * @return A new ModuleEntry.
      */
-    public static ModuleEntry create(String module, String path, ModuleEntry.Type type,
-            InputStream content, long size) {
-        Objects.requireNonNull(path);
-        Objects.requireNonNull(content);
-        return new ModuleEntryImpl(module, path, type, content, size);
+    public static ModuleEntry create(String path,
+            ModuleEntry.Type type, Path file) {
+        return ModuleEntryFactory.create(path, type, file);
+    }
+
+    /**
+     * Create a ModuleEntry for a resource of type {@link Type#CLASS_OR_RESOURCE}.
+     *
+     * @param path The resource path.
+     * @param file The resource file.
+     * @return A new ModuleEntry.
+     */
+    public static ModuleEntry create(String path, Path file) {
+        return create(path, Type.CLASS_OR_RESOURCE, file);
     }
 }
--- a/jdk/test/tools/jlink/ImageFilePoolTest.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/test/tools/jlink/ImageFilePoolTest.java	Fri Jun 24 19:56:50 2016 +0530
@@ -33,7 +33,7 @@
 import java.io.ByteArrayInputStream;
 import java.util.Optional;
 import java.util.function.Function;
-import jdk.tools.jlink.internal.ModuleEntryImpl;
+import jdk.tools.jlink.internal.ModuleEntryFactory;
 import jdk.tools.jlink.internal.ModulePoolImpl;
 import jdk.tools.jlink.plugin.ModuleEntry;
 import jdk.tools.jlink.plugin.ModulePool;
@@ -54,7 +54,7 @@
         ModulePool input = new ModulePoolImpl();
         for (int i = 0; i < 1000; ++i) {
             String module = "module" + (i / 100);
-            input.add(new InMemoryImageFile(module, "/" + module + "/java/class" + i,
+            input.add(newInMemoryImageFile("/" + module + "/java/class" + i,
                     ModuleEntry.Type.CONFIG, "class" + i));
         }
         if (input.getEntryCount() != 1000) {
@@ -94,11 +94,11 @@
             switch (index) {
                 case 0:
                     ++amountAfter;
-                    return new InMemoryImageFile(file.getModule(), file.getPath() + SUFFIX,
+                    return newInMemoryImageFile(file.getPath() + SUFFIX,
                             file.getType(), file.getPath());
                 case 1:
                     ++amountAfter;
-                    return new InMemoryImageFile(file.getModule(), file.getPath(),
+                    return newInMemoryImageFile(file.getPath(),
                             file.getType(), file.getPath());
             }
             return null;
@@ -130,28 +130,27 @@
         if (input.findEntry("unknown").isPresent()) {
             throw new AssertionError("ImageFileModulePool does not return null for unknown file");
         }
-        if (input.contains(new InMemoryImageFile("", "unknown", ModuleEntry.Type.CONFIG, "unknown"))) {
-            throw new AssertionError("'contain' returns true for unknown file");
+        if (input.contains(newInMemoryImageFile("/unknown/foo", ModuleEntry.Type.CONFIG, "unknown"))) {
+            throw new AssertionError("'contain' returns true for /unknown/foo file");
         }
-        input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
+        input.add(newInMemoryImageFile("/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
         try {
-            input.add(new InMemoryImageFile("", "/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
+            input.add(newInMemoryImageFile("/aaa/bbb", ModuleEntry.Type.CONFIG, ""));
             throw new AssertionError("Exception expected");
         } catch (Exception e) {
             // expected
         }
         input.setReadOnly();
         try {
-            input.add(new InMemoryImageFile("", "/aaa/ccc", ModuleEntry.Type.CONFIG, ""));
+            input.add(newInMemoryImageFile("/aaa/ccc", ModuleEntry.Type.CONFIG, ""));
             throw new AssertionError("Exception expected");
         } catch (Exception e) {
             // expected
         }
     }
 
-    private static class InMemoryImageFile extends ModuleEntryImpl {
-        public InMemoryImageFile(String module, String path, ModuleEntry.Type type, String content) {
-            super(module, path, type, new ByteArrayInputStream(content.getBytes()), content.getBytes().length);
-        }
+    private static ModuleEntry newInMemoryImageFile(String path,
+            ModuleEntry.Type type, String content) {
+        return ModuleEntryFactory.create(path, type, content.getBytes());
     }
 }
--- a/jdk/test/tools/jlink/ResourcePoolTest.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/test/tools/jlink/ResourcePoolTest.java	Fri Jun 24 19:56:50 2016 +0530
@@ -66,9 +66,7 @@
             String module = "/module" + (i / 10);
             String resourcePath = module + "/java/package" + i;
             byte[] bytes = resourcePath.getBytes();
-            input.add(ModuleEntry.create(module, resourcePath,
-                    ModuleEntry.Type.CLASS_OR_RESOURCE,
-                    new ByteArrayInputStream(bytes), bytes.length));
+            input.add(ModuleEntry.create(resourcePath, bytes));
         }
         ModulePool output = new ModulePoolImpl();
         ResourceVisitor visitor = new ResourceVisitor();
@@ -103,12 +101,11 @@
             switch (index) {
                 case 0:
                     ++amountAfter;
-                    return ModuleEntry.create(resource.getModule(), resource.getPath() + SUFFIX,
-                            resource.getType(), resource.stream(), resource.getLength());
+                    return ModuleEntry.create(resource.getPath() + SUFFIX,
+                            resource.getType(), resource.getBytes());
                 case 1:
                     ++amountAfter;
-                    return ModuleEntry.create(resource.getModule(), resource.getPath(),
-                            resource.getType(), resource.stream(), resource.getLength());
+                    return resource.create(resource.getBytes());
             }
             return null;
         }
@@ -132,9 +129,7 @@
         samples.add("javax/management/ObjectName");
         test(samples, (resources, module, path) -> {
             try {
-                resources.add(ModuleEntry.create(module, path,
-                        ModuleEntry.Type.CLASS_OR_RESOURCE,
-                        new ByteArrayInputStream(new byte[0]), 0));
+                resources.add(ModuleEntry.create(path, new byte[0]));
             } catch (Exception ex) {
                 throw new RuntimeException(ex);
             }
@@ -142,9 +137,7 @@
         test(samples, (resources, module, path) -> {
             try {
                 resources.add(ModulePoolImpl.
-                        newCompressedResource(ModuleEntry.create(module, path,
-                                ModuleEntry.Type.CLASS_OR_RESOURCE,
-                                new ByteArrayInputStream(new byte[0]), 0),
+                        newCompressedResource(ModuleEntry.create(path, new byte[0]),
                                 ByteBuffer.allocate(99), "bitcruncher", null,
                                 ((ModulePoolImpl)resources).getStringTable(), ByteOrder.nativeOrder()));
             } catch (Exception ex) {
@@ -203,20 +196,14 @@
 
     private void checkResourcesAfterCompression() throws Exception {
         ModulePoolImpl resources1 = new ModulePoolImpl();
-        ModuleEntry res1 = ModuleEntry.create("module1", "/module1/toto1",
-                ModuleEntry.Type.CLASS_OR_RESOURCE,
-                new ByteArrayInputStream(new byte[0]), 0);
-        ModuleEntry res2 = ModuleEntry.create("module2", "/module2/toto1",
-                ModuleEntry.Type.CLASS_OR_RESOURCE,
-                new ByteArrayInputStream(new byte[0]), 0);
+        ModuleEntry res1 = ModuleEntry.create("/module1/toto1", new byte[0]);
+        ModuleEntry res2 = ModuleEntry.create("/module2/toto1", new byte[0]);
         resources1.add(res1);
         resources1.add(res2);
 
         checkResources(resources1, res1, res2);
         ModulePool resources2 = new ModulePoolImpl();
-        ModuleEntry res3 = ModuleEntry.create("module2", "/module2/toto1",
-                ModuleEntry.Type.CLASS_OR_RESOURCE,
-                new ByteArrayInputStream(new byte[7]), 7);
+        ModuleEntry res3 = ModuleEntry.create("/module2/toto1", new byte[7]);
         resources2.add(res3);
         resources2.add(ModulePoolImpl.newCompressedResource(res1,
                 ByteBuffer.allocate(7), "zip", null, resources1.getStringTable(),
@@ -260,8 +247,7 @@
 
         ((ModulePoolImpl) resources).setReadOnly();
         try {
-            resources.add(ModuleEntry.create("module2",  "/module2/toto1",
-                    ModuleEntry.Type.CLASS_OR_RESOURCE, new ByteArrayInputStream(new byte[0]), 0));
+            resources.add(ModuleEntry.create("/module2/toto1", new byte[0]));
             throw new AssertionError("ModulePool is read-only, but an exception is not thrown");
         } catch (Exception ex) {
             // Expected
--- a/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/test/tools/jlink/plugins/ExcludeFilesPluginTest.java	Fri Jun 24 19:56:50 2016 +0530
@@ -74,8 +74,8 @@
         fplug.configure(prop);
         ModulePoolImpl files = new ModulePoolImpl();
         ModulePoolImpl fresult = new ModulePoolImpl();
-        ModuleEntry f = ModuleEntry.create(module, "/" + module + "/" + sample,
-                ModuleEntry.Type.CONFIG, new ByteArrayInputStream(new byte[0]), 0);
+        ModuleEntry f = ModuleEntry.create("/" + module + "/" + sample,
+                ModuleEntry.Type.CONFIG, new byte[0]);
         files.add(f);
 
         fplug.visit(files, fresult);
--- a/jdk/test/tools/jlink/plugins/ExcludePluginTest.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/test/tools/jlink/plugins/ExcludePluginTest.java	Fri Jun 24 19:56:50 2016 +0530
@@ -48,16 +48,16 @@
 
     public void test() throws Exception {
         check("**.jcov", "/num/toto.jcov", true);
-        check("**.jcov", "//toto.jcov", true);
+        check("**.jcov", "/toto.jcov/", true);
         check("**.jcov", "/toto.jcov/tutu/tata", false);
         check("/java.base/*.jcov", "/java.base/toto.jcov", true);
-        check("/java.base/toto.jcov", "t/java.base/iti.jcov", false);
+        check("/java.base/toto.jcov", "/tjava.base/iti.jcov", false);
         check("/java.base/*/toto.jcov", "/java.base/toto.jcov", false);
         check("/java.base/*/toto.jcov", "/java.base/tutu/toto.jcov", true);
         check("**/java.base/*/toto.jcov", "/tutu/java.base/tutu/toto.jcov", true);
         check("/META-INF/**", "/META-INF/services/  MyProvider ", true);
         check("/META-INF/**", "/META-INF/services/MyProvider", true);
-        check("**/META-INF", " /META-INF/services/MyProvider", false);
+        check("**/META-INF", "/ META-INF/services/MyProvider", false);
         check("**/META-INF/**", "/java.base//META-INF/services/MyProvider", true);
         check("/java.base/*/Toto$Titi.class", "/java.base/tutu/Toto$Titi.class", true);
         check("/**$**.class", "/java.base/tutu/Toto$Titi.class", true);
--- a/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/test/tools/jlink/plugins/ExcludeVMPluginTest.java	Fri Jun 24 19:56:50 2016 +0530
@@ -165,11 +165,11 @@
         // Create a pool with jvm.cfg and the input paths.
         byte[] jvmcfgContent = jvmcfg.getBytes();
         ModulePool pool = new ModulePoolImpl();
-        pool.add(ModuleEntry.create("java.base", "/java.base/native/jvm.cfg",
-                ModuleEntry.Type.NATIVE_LIB, new ByteArrayInputStream(jvmcfgContent), jvmcfgContent.length));
+        pool.add(ModuleEntry.create("/java.base/native/jvm.cfg",
+                ModuleEntry.Type.NATIVE_LIB, jvmcfgContent));
         for (String in : input) {
-            pool.add(ModuleEntry.create("java.base", in,
-                    ModuleEntry.Type.NATIVE_LIB, new ByteArrayInputStream(new byte[0]), 0));
+            pool.add(ModuleEntry.create(in,
+                    ModuleEntry.Type.NATIVE_LIB, new byte[0]));
         }
         ModulePool out = new ModulePoolImpl();
 
--- a/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java	Fri Jun 24 11:20:24 2016 -0300
+++ b/jdk/test/tools/jlink/plugins/StringSharingPluginTest.java	Fri Jun 24 19:56:50 2016 +0530
@@ -106,6 +106,9 @@
                     byte[] content = Files.readAllBytes(p);
                     String path = p.toString().replace('\\', '/');
                     path = path.substring("/modules".length());
+                    if (path.charAt(0) != '/') {
+                        path = "/" + path;
+                    }
                     ModuleEntry res = ModuleEntry.create(path, content);
                     resources.add(res);
                 } catch (Exception ex) {