changeset 15000:cf7e30f5c03f

8160829: Remove ASMPool support from jlink Reviewed-by: sundar, psandoz, forax
author jlaskey
date Thu, 07 Jul 2016 09:38:33 -0300
parents 8cc194337a0a
children 7791205bea66
files src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties src/jdk.jlink/share/classes/module-info.java test/tools/jlink/JLinkOptimTest.java test/tools/jlink/asmplugin/AddForgetResourcesTest.java test/tools/jlink/asmplugin/AsmPluginTestBase.java test/tools/jlink/asmplugin/BasicTest.java test/tools/jlink/asmplugin/IdentityPluginTest.java test/tools/jlink/asmplugin/NegativeTest.java test/tools/jlink/asmplugin/PackageMappingTest.java test/tools/jlink/asmplugin/SortingTest.java test/tools/jlink/asmplugin/VisitorTest.java
diffstat 23 files changed, 193 insertions(+), 5144 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/ClassForNamePlugin.java	Thu Jul 07 09:38:33 2016 -0300
@@ -0,0 +1,188 @@
+/*
+ * 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.plugins;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+import jdk.tools.jlink.plugin.ModulePool;
+import jdk.tools.jlink.plugin.Plugin.Category;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import static jdk.internal.org.objectweb.asm.ClassReader.*;
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
+import jdk.internal.org.objectweb.asm.tree.ClassNode;
+import jdk.internal.org.objectweb.asm.tree.InsnList;
+import jdk.internal.org.objectweb.asm.tree.LabelNode;
+import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
+import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
+import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
+import jdk.internal.org.objectweb.asm.tree.MethodNode;
+import jdk.tools.jlink.plugin.ModuleEntry;
+import jdk.tools.jlink.plugin.Plugin;
+
+public final class ClassForNamePlugin implements Plugin {
+    public static final String NAME = "class-for-name";
+
+    private static String binaryClassName(String path) {
+        return path.substring(path.indexOf('/', 1) + 1,
+                              path.length() - ".class".length());
+    }
+
+    private static int getAccess(ModuleEntry resource) {
+        ClassReader cr = new ClassReader(resource.getBytes());
+
+        return cr.getAccess();
+    }
+
+    private static String getPackage(String binaryName) {
+        int index = binaryName.lastIndexOf("/");
+
+        return index == -1 ? "" : binaryName.substring(0, index);
+    }
+
+    private ModuleEntry transform(ModuleEntry resource, Map<String, ModuleEntry> classes) {
+        byte[] inBytes = resource.getBytes();
+        ClassReader cr = new ClassReader(inBytes);
+        ClassNode cn = new ClassNode();
+        cr.accept(cn, EXPAND_FRAMES);
+        List<MethodNode> ms = cn.methods;
+        boolean modified = false;
+        LdcInsnNode ldc = null;
+
+        String thisPackage = getPackage(binaryClassName(resource.getPath()));
+
+        for (MethodNode mn : ms) {
+            InsnList il = mn.instructions;
+            Iterator<AbstractInsnNode> it = il.iterator();
+
+            while (it.hasNext()) {
+                AbstractInsnNode insn = it.next();
+
+                if (insn instanceof LdcInsnNode) {
+                    ldc = (LdcInsnNode)insn;
+                } else if (insn instanceof MethodInsnNode && ldc != null) {
+                    MethodInsnNode min = (MethodInsnNode)insn;
+
+                    if (min.getOpcode() == Opcodes.INVOKESTATIC &&
+                        min.name.equals("forName") &&
+                        min.owner.equals("java/lang/Class") &&
+                        min.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
+                        String ldcClassName = ldc.cst.toString();
+                        String thatClassName = ldcClassName.replaceAll("\\.", "/");
+                        ModuleEntry thatClass = classes.get(thatClassName);
+
+                        if (thatClass != null) {
+                            int thatAccess = getAccess(thatClass);
+                            String thatPackage = getPackage(thatClassName);
+
+                            if ((thatAccess & Opcodes.ACC_PRIVATE) != Opcodes.ACC_PRIVATE &&
+                                ((thatAccess & Opcodes.ACC_PUBLIC) == Opcodes.ACC_PUBLIC ||
+                                  thisPackage.equals(thatPackage))) {
+                                Type type = Type.getObjectType(thatClassName);
+                                il.remove(ldc);
+                                il.set(min, new LdcInsnNode(type));
+                                modified = true;
+                            }
+                        }
+                    }
+
+                    ldc = null;
+                } else if (!(insn instanceof LabelNode) &&
+                           !(insn instanceof LineNumberNode)) {
+                    ldc = null;
+                }
+
+            }
+        }
+
+        if (modified) {
+            ClassWriter cw = new ClassWriter(cr, 0);
+            cn.accept(cw);
+            byte[] outBytes = cw.toByteArray();
+
+            return resource.create(outBytes);
+        }
+
+        return resource;
+    }
+
+    @Override
+    public String getName() {
+        return NAME;
+    }
+
+    @Override
+    public void visit(ModulePool in, ModulePool out) {
+        Objects.requireNonNull(in);
+        Objects.requireNonNull(out);
+        Map<String, ModuleEntry> classes = in.entries()
+            .filter(resource -> resource != null &&
+                    resource.getPath().endsWith(".class") &&
+                    !resource.getPath().endsWith("/module-info.class"))
+            .collect(Collectors.toMap(resource -> binaryClassName(resource.getPath()),
+                                      resource -> resource));
+        in.entries()
+            .filter(resource -> resource != null)
+            .forEach(resource -> {
+                String path = resource.getPath();
+
+                if (path.endsWith(".class") && !path.endsWith("/module-info.class")) {
+                    out.add(transform(resource, classes));
+                } else {
+                    out.add(resource);
+                }
+            });
+    }
+
+    @Override
+    public Category getType() {
+        return Category.TRANSFORMER;
+    }
+
+    @Override
+    public boolean hasArguments() {
+        return false;
+    }
+
+    @Override
+    public String getDescription() {
+        return PluginsResourceBundle.getDescription(NAME);
+    }
+
+    @Override
+    public String getArgumentsDescription() {
+       return PluginsResourceBundle.getArgument(NAME);
+    }
+
+    @Override
+    public void configure(Map<String, String> config) {
+
+    }
+}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/OptimizationPlugin.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,285 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.UncheckedIOException;
-import java.nio.charset.StandardCharsets;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Consumer;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.optim.ForNameFolding;
-import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.TypeResolver;
-import jdk.tools.jlink.plugin.PluginException;
-
-/**
- *
- * Optimize Classes following various strategies. Strategies are implementation
- * of <code>ClassOptimizer</code> and <code>MethodOptimizer</code>.
- */
-public final class OptimizationPlugin extends AsmPlugin {
-
-    public static final String NAME = "class-optim";
-    public static final String LOG  = "log";
-    public static final String ALL = "all";
-    public static final String FORNAME_REMOVAL = "forName-folding";
-
-    /**
-     * Default resolver. A resolver that retrieve types that are in an
-     * accessible package, are public or are located in the same package as the
-     * caller.
-     */
-    private static final class DefaultTypeResolver implements TypeResolver {
-
-        private final Set<String> packages;
-        private final AsmPools pools;
-
-        DefaultTypeResolver(AsmPools pools, AsmModulePool modulePool) {
-            Objects.requireNonNull(pools);
-            Objects.requireNonNull(modulePool);
-            this.pools = pools;
-            packages = pools.getGlobalPool().getAccessiblePackages(modulePool.getModuleName());
-        }
-
-        @Override
-        public ClassReader resolve(ClassNode cn, MethodNode mn, String type) {
-            int classIndex = cn.name.lastIndexOf("/");
-            String callerPkg = classIndex == -1 ? ""
-                    : cn.name.substring(0, classIndex);
-            int typeClassIndex = type.lastIndexOf("/");
-            String pkg = typeClassIndex == - 1 ? ""
-                    : type.substring(0, typeClassIndex);
-            ClassReader reader = null;
-            if (packages.contains(pkg) || pkg.equals(callerPkg)) {
-                ClassReader r = pools.getGlobalPool().getClassReader(type);
-                if (r != null) {
-                    // if not private
-                    if ((r.getAccess() & Opcodes.ACC_PRIVATE)
-                            != Opcodes.ACC_PRIVATE) {
-                        // public
-                        if (((r.getAccess() & Opcodes.ACC_PUBLIC)
-                                == Opcodes.ACC_PUBLIC)) {
-                            reader = r;
-                        } else if (pkg.equals(callerPkg)) {
-                            reader = r;
-                        }
-                    }
-                }
-            }
-            return reader;
-        }
-    }
-
-    public interface Optimizer {
-
-        void close() throws IOException;
-    }
-
-    public interface ClassOptimizer extends Optimizer {
-
-        boolean optimize(Consumer<String> logger, AsmPools pools,
-                AsmModulePool modulePool,
-                ClassNode cn) throws Exception;
-    }
-
-    public interface MethodOptimizer extends Optimizer {
-
-        boolean optimize(Consumer<String> logger, AsmPools pools,
-                AsmModulePool modulePool,
-                ClassNode cn, MethodNode m, TypeResolver resolver) throws Exception;
-    }
-
-    private List<Optimizer> optimizers = new ArrayList<>();
-
-    private OutputStream stream;
-    private int numMethods;
-
-    private void log(String content) {
-        if (stream != null) {
-            try {
-                content = content + "\n";
-                stream.write(content.getBytes(StandardCharsets.UTF_8));
-            } catch (IOException ex) {
-                System.err.println(ex);
-            }
-        }
-    }
-
-    private void close() throws IOException {
-        log("Num analyzed methods " + numMethods);
-
-        for (Optimizer optimizer : optimizers) {
-            try {
-                optimizer.close();
-            } catch (IOException ex) {
-                System.err.println("Error closing optimizer " + ex);
-            }
-        }
-        if (stream != null) {
-            stream.close();
-        }
-    }
-
-    @Override
-    public String getName() {
-        return NAME;
-    }
-
-    @Override
-    public void visit(AsmPools pools) {
-        try {
-            for (AsmModulePool p : pools.getModulePools()) {
-                DefaultTypeResolver resolver = new DefaultTypeResolver(pools, p);
-                p.visitClassReaders((reader) -> {
-                    ClassWriter w = null;
-                    try {
-                        w = optimize(pools, p, reader, resolver);
-                    } catch (IOException ex) {
-                        throw new PluginException("Problem optimizing "
-                                + reader.getClassName(), ex);
-                    }
-                    return w;
-                });
-            }
-        } finally {
-            try {
-                close();
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-    }
-
-    private ClassWriter optimize(AsmPools pools, AsmModulePool modulePool,
-            ClassReader reader, TypeResolver resolver)
-            throws IOException {
-        ClassNode cn = new ClassNode();
-        ClassWriter writer = null;
-        if ((reader.getAccess() & Opcodes.ACC_INTERFACE) == 0) {
-            reader.accept(cn, ClassReader.EXPAND_FRAMES);
-            boolean optimized = false;
-            for (Optimizer optimizer : optimizers) {
-                if (optimizer instanceof ClassOptimizer) {
-                    try {
-                        boolean optim = ((ClassOptimizer) optimizer).
-                                optimize(this::log, pools, modulePool, cn);
-                        if (optim) {
-                            optimized = true;
-                        }
-                    } catch (Throwable ex) {
-                        throw new PluginException("Exception optimizing "
-                                + reader.getClassName(), ex);
-                    }
-                } else {
-                    MethodOptimizer moptimizer = (MethodOptimizer) optimizer;
-                    for (MethodNode m : cn.methods) {
-                        if ((m.access & Opcodes.ACC_ABSTRACT) == 0
-                                && (m.access & Opcodes.ACC_NATIVE) == 0) {
-                            numMethods += 1;
-                            try {
-                                boolean optim = moptimizer.
-                                        optimize(this::log, pools, modulePool, cn,
-                                                m, resolver);
-                                if (optim) {
-                                    optimized = true;
-                                }
-                            } catch (Throwable ex) {
-                                throw new PluginException("Exception optimizing "
-                                        + reader.getClassName() + "." + m.name, ex);
-                            }
-
-                        }
-                    }
-                }
-            }
-
-            if (optimized) {
-                writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
-                try {
-                    // add a validation layer in between to check for class vallidity
-                    CheckClassAdapter ca = new CheckClassAdapter(writer);
-                    cn.accept(ca);
-                } catch (Exception ex) {
-                    throw new PluginException("Exception optimizing class " + cn.name, ex);
-                }
-            }
-        }
-        return writer;
-    }
-
-    @Override
-    public String getDescription() {
-        return PluginsResourceBundle.getDescription(NAME);
-    }
-
-    @Override
-    public boolean hasArguments() {
-        return true;
-    }
-
-    @Override
-    public String getArgumentsDescription() {
-       return PluginsResourceBundle.getArgument(NAME);
-    }
-
-    @Override
-    public void configure(Map<String, String> config) {
-        String strategies = config.get(NAME);
-        String[] arr = strategies.split(",");
-        for (String s : arr) {
-            if (s.equals(ALL)) {
-                optimizers.clear();
-                optimizers.add(new ForNameFolding());
-                break;
-            } else if (s.equals(FORNAME_REMOVAL)) {
-                optimizers.add(new ForNameFolding());
-            } else {
-                throw new IllegalArgumentException("Unknown optimization: " + s);
-            }
-        }
-        String f = config.get(LOG);
-        if (f != null) {
-            try {
-                stream = new FileOutputStream(f);
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmGlobalPool.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.asm;
-
-import java.util.Set;
-
-/**
- * A pool containing all class and resource files.
- */
-public interface AsmGlobalPool extends AsmPool {
-
-    /**
-     * Associate a package to a module, useful when adding new classes in new
-     * packages. WARNING: In order to properly handle new package and/or new
-     * module, module-info class must be added and/or updated.
-     *
-     * @param pkg The new package, following java binary syntax (/-separated
-     * path name).
-     * @param module An existing or new module.
-     * @throws jdk.tools.jlink.plugins.PluginException If a mapping already
-     * exist for this package.
-     */
-    public void addPackageModuleMapping(String pkg, String module);
-
-    /**
-     * Return the set of accessible packages for a given module.
-     *
-     * @param module The module from which packages are accessible.
-     * @return Set of packages or null if the module is not found.
-     */
-    public Set<String> getAccessiblePackages(String module);
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmModulePool.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.asm;
-
-import java.lang.module.ModuleDescriptor;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-
-/**
- * A pool for a given module
- */
-public interface AsmModulePool extends AsmPool {
-
-    /**
-     * Associate a package to this module, useful when adding new classes in new
-     * packages. WARNING: In order to properly handle new package and/or new
-     * module, module-info class must be added and/or updated.
-     *
-     * @param pkg The new package, following java binary syntax (/-separated
-     * path name).
-     * @throws jdk.tools.jlink.plugins.PluginException If a mapping already
-     * exist for this package.
-     */
-    public void addPackage(String pkg);
-
-    /**
-     * The module name of this pool.
-     * @return The module name;
-     */
-    public String getModuleName();
-
-    /**
-     * Lookup the class in this pool and the required pools. NB: static module
-     * readability can be different at execution time.
-     *
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     * @throws jdk.tools.jlink.plugins.PluginException
-     */
-    public ClassReader getClassReaderInDependencies(String binaryName);
-
-    /**
-     * Lookup the class in the exported packages of this module. "public
-     * requires" modules are looked up. NB: static module readability can be
-     * different at execution time.
-     *
-     * @param callerModule Name of calling module.
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     * @throws jdk.tools.jlink.plugins.PluginException
-     */
-    public ClassReader getExportedClassReader(String callerModule,
-            String binaryName);
-
-    /**
-     * The module descriptor.
-     *
-     * @return The module descriptor;
-     */
-    public ModuleDescriptor getDescriptor();
-
-    /**
-     * Retrieve the internal and exported packages.
-     *
-     * @return
-     */
-    public Set<String> getAllPackages();
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPlugin.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.asm;
-
-import java.util.Objects;
-import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-
-/**
- * Extend this class to develop your own plugin in order to transform jimage
- * resources.
- *
- */
-public abstract class AsmPlugin implements Plugin {
-
-    public AsmPlugin() {
-    }
-
-    @Override
-    public void visit(ModulePool allContent, ModulePool outResources) {
-        Objects.requireNonNull(allContent);
-        Objects.requireNonNull(outResources);
-        ModulePoolImpl resources = new ModulePoolImpl(allContent.getByteOrder());
-        allContent.entries().forEach(md -> {
-            if(md.getType().equals(ModuleEntry.Type.CLASS_OR_RESOURCE)) {
-                resources.add(md);
-            } else {
-                outResources.add(md);
-            }
-        });
-        AsmPools pools = new AsmPools(resources);
-        visit(pools);
-        pools.fillOutputResources(outResources);
-    }
-
-    /**
-     * This is the method to implement in order to
-     * apply Asm transformation to jimage contained classes.
-     * @param pools The pool of Asm classes and other resource files.
-     * @param strings To add a string to the jimage strings table.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public abstract void visit(AsmPools pools);
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPool.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,314 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.asm;
-
-import java.util.Collection;
-import java.util.List;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-/**
- * A pool of ClassReader and other resource files.
- * This class allows to transform and sort classes and resource files.
- * <p>
- * Classes in the class pool are named following java binary name specification.
- * For example, java.lang.Object class is named java/lang/Object
- * <p>
- * Module information has been stripped out from class and other resource files
- * (.properties, binary files, ...).</p>
- */
-public interface AsmPool {
-
-    /**
-     * A resource that is not a class file.
-     * <p>
-     * The path of a resource is a /-separated path name that identifies the
-     * resource. For example com.foo.bar.Bundle.properties resource name is
-     * com/foo/bar/Bundle.properties </p>
-     * <p>
-     */
-    public class ResourceFile {
-
-        private final String path;
-        private final byte[] content;
-
-        public ResourceFile(String path, byte[] content) {
-            this.path = path;
-            this.content = content;
-        }
-
-        public String getPath() {
-            return path;
-        }
-
-        public byte[] getContent() {
-            return content;
-        }
-    }
-
-    /**
-     * To visit each Class contained in the pool
-     */
-    public interface ClassReaderVisitor {
-
-        /**
-         * Called for each ClassReader located in the pool.
-         *
-         * @param reader A class reader.
-         * @return A writer or null if the class has not been transformed.
-         */
-        public ClassWriter visit(ClassReader reader);
-    }
-
-    /**
-     * To visit each Resource contained in the pool
-     */
-    public interface ResourceFileVisitor {
-
-        /**
-         * Called for each Resource file located in the pool.
-         *
-         * @param reader A resource file.
-         * @return A resource file or null if the resource has not been
-         * transformed.
-         */
-        public ResourceFile visit(ResourceFile reader);
-    }
-
-    /**
-     * Contains the transformed classes. When the jimage file is generated,
-     * transformed classes take precedence on unmodified ones.
-     */
-    public interface WritableClassPool {
-
-        /**
-         * Add a class to the pool, if a class already exists, it is replaced.
-         *
-         * @param writer The class writer.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public void addClass(ClassWriter writer);
-
-        /**
-         * The class will be not added to the jimage file.
-         *
-         * @param className The class name to forget.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public void forgetClass(String className);
-
-        /**
-         * Get a transformed class.
-         *
-         * @param binaryName The java class binary name
-         * @return The ClassReader or null if the class is not found.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public ClassReader getClassReader(String binaryName);
-
-        /**
-         * Get a transformed class.
-         *
-         * @param res A class resource.
-         * @return The ClassReader or null if the class is not found.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public ClassReader getClassReader(ModuleEntry res);
-
-        /**
-         * Returns all the classes contained in the writable pool.
-         *
-         * @return The collection of classes.
-         */
-        public Collection<ModuleEntry> getClasses();
-    }
-
-    /**
-     * Contains the transformed resources. When the jimage file is generated,
-     * transformed resources take precedence on unmodified ones.
-     */
-    public interface WritableResourcePool {
-
-        /**
-         * Add a resource, if the resource exists, it is replaced.
-         *
-         * @param resFile The resource file to add.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public void addResourceFile(ResourceFile resFile);
-
-        /**
-         * The resource will be not added to the jimage file.
-         *
-         * @param resourceName
-         * @throws jdk.tools.jlink.plugin.PluginException If the resource to
-         * forget doesn't exist or is null.
-         */
-        public void forgetResourceFile(String resourceName);
-
-        /**
-         * Get a transformed resource.
-         *
-         * @param name The java resource name
-         * @return The Resource or null if the resource is not found.
-         */
-        public ResourceFile getResourceFile(String name);
-
-        /**
-         * Get a transformed resource.
-         *
-         * @param res The java resource
-         * @return The Resource or null if the resource is not found.
-         */
-        public ResourceFile getResourceFile(ModuleEntry res);
-
-        /**
-         * Returns all the resources contained in the writable pool.
-         *
-         * @return The array of resources.
-         */
-        public Collection<ModuleEntry> getResourceFiles();
-    }
-
-    /**
-     * To order the classes and resources within a jimage file.
-     */
-    public interface Sorter {
-
-        /**
-         * @param resources The resources will be added to the jimage following
-         * the order of this ResourcePool.
-         * @return The resource paths ordered in the way to use for storage in the jimage.
-         * @throws jdk.tools.jlink.plugin.PluginException
-         */
-        public List<String> sort(ModulePool resources);
-    }
-
-    /**
-     * The writable pool used to store transformed resources.
-     *
-     * @return The writable pool.
-     */
-    public WritableClassPool getTransformedClasses();
-
-    /**
-     * The writable pool used to store transformed resource files.
-     *
-     * @return The writable pool.
-     */
-    public WritableResourcePool getTransformedResourceFiles();
-
-    /**
-     * Set a sorter instance to sort all files. If no sorter is set, then input
-     * Resources will be added in the order they have been received followed by
-     * newly added resources.
-     *
-     * @param sorter
-     */
-    public void setSorter(Sorter sorter);
-
-    /**
-     * Returns the classes contained in the pool.
-     *
-     * @return The classes.
-     */
-    public Collection<ModuleEntry> getClasses();
-
-    /**
-     * Returns the resources contained in the pool. Resources are all the file
-     * that are not classes (eg: properties file, binary files, ...)
-     *
-     * @return The array of resource files.
-     */
-    public Collection<ModuleEntry> getResourceFiles();
-
-    /**
-     * Retrieves a resource based on the binary name. This name doesn't contain
-     * the module name.
-     * <b>NB:</b> When dealing with resources that have the same name in various
-     * modules (eg: META-INFO/*), you should use the <code>ResourcePool</code>
-     * referenced from this <code>AsmClassPool</code>.
-     *
-     * @param binaryName Name of a Java resource or null if the resource doesn't
-     * exist.
-     * @return
-     */
-    public ResourceFile getResourceFile(String binaryName);
-
-    /**
-     * Retrieves a resource for the passed resource.
-     *
-     * @param res The resource
-     * @return The resource file or null if it doesn't exist.
-     */
-    public ResourceFile getResourceFile(ModuleEntry res);
-
-    /**
-     * Retrieve a ClassReader from the pool.
-     *
-     * @param binaryName Class binary name
-     * @return A reader or null if the class is unknown
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public ClassReader getClassReader(String binaryName);
-
-    /**
-     * Retrieve a ClassReader from the pool.
-     *
-     * @param res A resource.
-     * @return A reader or null if the class is unknown
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public ClassReader getClassReader(ModuleEntry res);
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public void visitClassReaders(ClassReaderVisitor visitor);
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public void visitResourceFiles(ResourceFileVisitor visitor);
-
-    /**
-     * Returns the pool of all the resources (transformed and unmodified).
-     * The input resources are replaced by the transformed ones.
-     * If a sorter has been set, it is used to sort the returned resources.
-     *
-     * @param output The pool used to fill the jimage.
-     * @throws jdk.tools.jlink.plugin.PluginException
-     */
-    public void fillOutputResources(ModulePool output);
-
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPoolImpl.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,698 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.asm;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Requires;
-import java.lang.module.ModuleDescriptor.Requires.Modifier;
-import java.lang.module.ModuleDescriptor.Exports;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.internal.ImageFileCreator;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
-
-/**
- * A pool of ClassReader and other resource files. This class allows to
- * transform and sort classes and resource files.
- * <p>
- * Classes in the class pool are named following java binary name specification.
- * For example, java.lang.Object class is named java/lang/Object
- * <p>
- * Module information has been stripped out from class and other resource files
- * (.properties, binary files, ...).</p>
- */
-final class AsmPoolImpl implements AsmModulePool {
-
-    /**
-     * Contains the transformed classes. When the jimage file is generated,
-     * transformed classes take precedence on unmodified ones.
-     */
-    public final class WritableClassPoolImpl implements WritableClassPool {
-
-        private WritableClassPoolImpl() {
-        }
-
-        /**
-         * Add a class to the pool, if a class already exists, it is replaced.
-         *
-         * @param writer The class writer.
-         * @throws java.io.IOException
-         */
-        @Override
-        public void addClass(ClassWriter writer) {
-            Objects.requireNonNull(writer);
-            // Retrieve the className
-            ClassReader reader = newClassReader(writer.toByteArray());
-            String className = reader.getClassName();
-            String path;
-            if (className.endsWith("module-info")) {
-                // remove the module name contained in the class name
-                className = className.substring(className.indexOf("/") + 1);
-                path = "/" + moduleName + "/" + className;
-            } else {
-                path = toClassNamePath(className);
-            }
-
-            byte[] content = writer.toByteArray();
-            ModuleEntry res = ModuleEntry.create(path, content);
-            transformedClasses.put(className, res);
-        }
-
-        /**
-         * The class will be not added to the jimage file.
-         *
-         * @param className The class name to forget.
-         */
-        @Override
-        public void forgetClass(String className) {
-            Objects.requireNonNull(className);
-            // do we have a resource?
-            ModuleEntry res = transformedClasses.get(className);
-            if (res == null) {
-                res = inputClasses.get(className);
-                if (res == null) {
-                    throw new PluginException("Unknown class " + className);
-                }
-            }
-            String path = toClassNamePath(className);
-            forgetResources.add(path);
-            // Just in case it has been added.
-            transformedClasses.remove(className);
-        }
-
-        /**
-         * Get a transformed class.
-         *
-         * @param binaryName The java class binary name
-         * @return The ClassReader or null if the class is not found.
-         */
-        @Override
-        public ClassReader getClassReader(String binaryName) {
-            Objects.requireNonNull(binaryName);
-            ModuleEntry res = transformedClasses.get(binaryName);
-            ClassReader reader = null;
-            if (res != null) {
-                reader = getClassReader(res);
-            }
-            return reader;
-        }
-
-        /**
-         * Returns all the classes contained in the writable pool.
-         *
-         * @return The array of transformed classes.
-         */
-        @Override
-        public Collection<ModuleEntry> getClasses() {
-            List<ModuleEntry> classes = new ArrayList<>();
-            for (Entry<String, ModuleEntry> entry : transformedClasses.entrySet()) {
-                classes.add(entry.getValue());
-            }
-            return classes;
-        }
-
-        @Override
-        public ClassReader getClassReader(ModuleEntry res) {
-            return newClassReader(res.getBytes());
-        }
-    }
-
-    /**
-     * Contains the transformed resources. When the jimage file is generated,
-     * transformed resources take precedence on unmodified ones.
-     */
-    public final class WritableResourcePoolImpl implements WritableResourcePool {
-
-        private WritableResourcePoolImpl() {
-        }
-
-        /**
-         * Add a resource, if the resource exists, it is replaced.
-         *
-         * @param resFile The resource file to add.
-         */
-        @Override
-        public void addResourceFile(ResourceFile resFile) {
-            Objects.requireNonNull(resFile);
-            String path = toResourceNamePath(resFile.getPath());
-            ModuleEntry res = ModuleEntry.create(path, resFile.getContent());
-            transformedResources.put(resFile.getPath(), res);
-        }
-
-        /**
-         * The resource will be not added to the jimage file.
-         *
-         * @param resourceName
-         * @throws java.io.IOException
-         */
-        @Override
-        public void forgetResourceFile(String resourceName) {
-            Objects.requireNonNull(resourceName);
-            String path = toResourceNamePath(resourceName);
-            // do we have a resource?
-            ModuleEntry res = transformedResources.get(resourceName);
-            if (res == null) {
-                res = inputResources.get(resourceName);
-                if (res == null) {
-                    throw new PluginException("Unknown resource " + resourceName);
-                }
-            }
-            forgetResources.add(path);
-            // Just in case it has been added.
-            transformedResources.remove(resourceName);
-        }
-
-        /**
-         * Get a transformed resource.
-         *
-         * @param name The java resource name
-         * @return The Resource or null if the resource is not found.
-         */
-        @Override
-        public ResourceFile getResourceFile(String name) {
-            Objects.requireNonNull(name);
-            ModuleEntry res = transformedResources.get(name);
-            ResourceFile resFile = null;
-            if (res != null) {
-                resFile = getResourceFile(res);
-            }
-            return resFile;
-        }
-
-        /**
-         * Returns all the resources contained in the writable pool.
-         *
-         * @return The array of transformed classes.
-         */
-        @Override
-        public Collection<ModuleEntry> getResourceFiles() {
-            List<ModuleEntry> resources = new ArrayList<>();
-            for (Entry<String, ModuleEntry> entry : transformedResources.entrySet()) {
-                resources.add(entry.getValue());
-            }
-            return resources;
-        }
-
-        @Override
-        public ResourceFile getResourceFile(ModuleEntry res) {
-            return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
-                    res.getBytes());
-        }
-    }
-
-    private final ModulePool jimageResources;
-    private final Map<String, ModuleEntry> inputClasses;
-    private final Map<String, ModuleEntry> inputResources;
-    private final Map<String, String> inputClassPackageMapping;
-    private final Map<String, String> inputOtherPackageMapping;
-
-    private final WritableClassPool transClassesPool
-            = new WritableClassPoolImpl();
-    private final WritableResourcePool transResourcesPool
-            = new WritableResourcePoolImpl();
-
-    private Sorter sorter;
-
-    private final Map<String, ModuleEntry> transformedClasses
-            =            new LinkedHashMap<>();
-    private final Map<String, ModuleEntry> transformedResources
-            =            new LinkedHashMap<>();
-    private final List<String> forgetResources = new ArrayList<>();
-    private final Map<String, String> newPackageMapping = new HashMap<>();
-
-    private final String moduleName;
-
-    private final ModuleDescriptor descriptor;
-    private final AsmPools pools;
-
-    /**
-     * A new Asm pool.
-     *
-     * @param inputResources The raw resources to build the pool from.
-     * @param moduleName The name of a module.
-     * @param pools The resource pools.
-     * @param descriptor The module descriptor.
-     */
-    AsmPoolImpl(ModulePool inputResources, String moduleName,
-            AsmPools pools,
-            ModuleDescriptor descriptor) {
-        Objects.requireNonNull(inputResources);
-        Objects.requireNonNull(moduleName);
-        Objects.requireNonNull(pools);
-        Objects.requireNonNull(descriptor);
-        this.jimageResources = inputResources;
-        this.moduleName = moduleName;
-        this.pools = pools;
-        this.descriptor = descriptor;
-        Map<String, ModuleEntry> classes = new LinkedHashMap<>();
-        Map<String, ModuleEntry> resources = new LinkedHashMap<>();
-        Map<String, String> packageClassToModule = new HashMap<>();
-        Map<String, String> packageOtherToModule = new HashMap<>();
-        inputResources.entries().forEach(res -> {
-            if (res.getPath().endsWith(".class")) {
-                classes.put(toJavaBinaryClassName(res.getPath()), res);
-            } else {
-                resources.put(toJavaBinaryResourceName(res.getPath()), res);
-            }
-            String[] split = ImageFileCreator.splitPath(res.getPath());
-            if (ImageFileCreator.isClassPackage(res.getPath())) {
-                packageClassToModule.put(split[1], res.getModule());
-            } else {
-                // Keep a map of other resources
-                // Same resource names such as META-INF/* should be handled with full path name.
-                if (!split[1].isEmpty()) {
-                    packageOtherToModule.put(split[1], res.getModule());
-                }
-            }
-        });
-        this.inputClasses = Collections.unmodifiableMap(classes);
-        this.inputResources = Collections.unmodifiableMap(resources);
-
-        this.inputClassPackageMapping = Collections.unmodifiableMap(packageClassToModule);
-        this.inputOtherPackageMapping = Collections.unmodifiableMap(packageOtherToModule);
-    }
-
-    @Override
-    public String getModuleName() {
-        return moduleName;
-    }
-
-    /**
-     * The writable pool used to store transformed resources.
-     *
-     * @return The writable pool.
-     */
-    @Override
-    public WritableClassPool getTransformedClasses() {
-        return transClassesPool;
-    }
-
-    /**
-     * The writable pool used to store transformed resource files.
-     *
-     * @return The writable pool.
-     */
-    @Override
-    public WritableResourcePool getTransformedResourceFiles() {
-        return transResourcesPool;
-    }
-
-    /**
-     * Set a sorter instance to sort all files. If no sorter is set, then input
-     * Resources will be added in the order they have been received followed by
-     * newly added resources.
-     *
-     * @param sorter
-     */
-    @Override
-    public void setSorter(Sorter sorter) {
-        this.sorter = sorter;
-    }
-
-    /**
-     * Returns the classes contained in the pool.
-     *
-     * @return The array of classes.
-     */
-    @Override
-    public Collection<ModuleEntry> getClasses() {
-        return inputClasses.values();
-    }
-
-    /**
-     * Returns the resources contained in the pool. Resources are all the file
-     * that are not classes (eg: properties file, binary files, ...)
-     *
-     * @return The array of classes.
-     */
-    @Override
-    public Collection<ModuleEntry> getResourceFiles() {
-        return inputResources.values();
-    }
-
-    /**
-     * Retrieves a resource based on the binary name. This name doesn't contain
-     * the module name.
-     * <b>NB:</b> When dealing with resources that have the same name in various
-     * modules (eg: META-INFO/*), you should use the <code>ResourcePool</code>
-     * referenced from this <code>AsmClassPool</code>.
-     *
-     * @param binaryName Name of a Java resource or null if the resource doesn't
-     * exist.
-     * @return
-     */
-    @Override
-    public ResourceFile getResourceFile(String binaryName) {
-        Objects.requireNonNull(binaryName);
-        ModuleEntry res = inputResources.get(binaryName);
-        ResourceFile resFile = null;
-        if (res != null) {
-            resFile = getResourceFile(res);
-        }
-        return resFile;
-    }
-
-    /**
-     * Retrieve a ClassReader from the pool.
-     *
-     * @param binaryName Class binary name
-     * @return A reader or null if the class is unknown
-     */
-    @Override
-    public ClassReader getClassReader(String binaryName) {
-        Objects.requireNonNull(binaryName);
-        ModuleEntry res = inputClasses.get(binaryName);
-        ClassReader reader = null;
-        if (res != null) {
-            reader = getClassReader(res);
-        }
-        return reader;
-    }
-
-    @Override
-    public ResourceFile getResourceFile(ModuleEntry res) {
-        return new ResourceFile(toJavaBinaryResourceName(res.getPath()),
-                res.getBytes());
-    }
-
-    @Override
-    public ClassReader getClassReader(ModuleEntry res) {
-        return newClassReader(res.getBytes());
-    }
-
-    /**
-     * Lookup the class in this pool and the required pools. NB: static module
-     * readability can be different at execution time.
-     *
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     */
-    @Override
-    public ClassReader getClassReaderInDependencies(String binaryName) {
-        Objects.requireNonNull(binaryName);
-        ClassReader reader = getClassReader(binaryName);
-        if (reader == null) {
-            for (Requires requires : descriptor.requires()) {
-                AsmModulePool pool = pools.getModulePool(requires.name());
-                reader = pool.getExportedClassReader(moduleName, binaryName);
-                if (reader != null) {
-                    break;
-                }
-            }
-        }
-        return reader;
-    }
-
-    /**
-     * Lookup the class in the exported packages of this module. "public
-     * requires" modules are looked up. NB: static module readability can be
-     * different at execution time.
-     *
-     * @param callerModule Name of calling module.
-     * @param binaryName The class to lookup.
-     * @return The reader or null if not found
-     */
-    @Override
-    public ClassReader getExportedClassReader(String callerModule, String binaryName) {
-        Objects.requireNonNull(callerModule);
-        Objects.requireNonNull(binaryName);
-        boolean exported = false;
-        ClassReader clazz = null;
-        for (Exports e : descriptor.exports()) {
-            String pkg = e.source();
-            Set<String> targets = e.targets();
-            System.out.println("PKG " + pkg);
-            if (targets.isEmpty() || targets.contains(callerModule)) {
-                if (binaryName.startsWith(pkg)) {
-                    String className = binaryName.substring(pkg.length());
-                    System.out.println("CLASS " + className);
-                    exported = !className.contains(".");
-                }
-                if (exported) {
-                    break;
-                }
-            }
-        }
-        // public requires (re-export)
-        if (!exported) {
-            for (Requires requires : descriptor.requires()) {
-                if (requires.modifiers().contains(Modifier.PUBLIC)) {
-                    AsmModulePool pool = pools.getModulePool(requires.name());
-                    clazz = pool.getExportedClassReader(moduleName, binaryName);
-                    if (clazz != null) {
-                        break;
-                    }
-                }
-            }
-        } else {
-            clazz = getClassReader(binaryName);
-        }
-        return clazz;
-
-    }
-
-    @Override
-    public ModuleDescriptor getDescriptor() {
-        return descriptor;
-    }
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     */
-    @Override
-    public void visitClassReaders(ClassReaderVisitor visitor) {
-        Objects.requireNonNull(visitor);
-        for (ModuleEntry res : getClasses()) {
-            ClassReader reader = newClassReader(res.getBytes());
-            ClassWriter writer = visitor.visit(reader);
-            if (writer != null) {
-
-                getTransformedClasses().addClass(writer);
-            }
-        }
-    }
-
-    /**
-     * To visit the set of ClassReaders.
-     *
-     * @param visitor The visitor.
-     */
-    @Override
-    public void visitResourceFiles(ResourceFileVisitor visitor) {
-        Objects.requireNonNull(visitor);
-        for (ModuleEntry resource : getResourceFiles()) {
-            ResourceFile resFile
-                    = new ResourceFile(toJavaBinaryResourceName(resource.getPath()),
-                            resource.getBytes());
-            ResourceFile res = visitor.visit(resFile);
-            if (res != null) {
-                getTransformedResourceFiles().addResourceFile(res);
-            }
-        }
-    }
-
-    /**
-     * Returns the pool of all the resources (transformed and unmodified). The
-     * input resources are replaced by the transformed ones. If a sorter has
-     * been set, it is used to sort the returned resources.     *
-     */
-    @Override
-    public void fillOutputResources(ModulePool outputResources) {
-        List<String> added = new ArrayList<>();
-        // If the sorter is null, use the input order.
-        // New resources are added at the end
-        // First input classes that have not been removed
-        ModulePool output = new ModulePoolImpl(outputResources.getByteOrder(),
-                ((ModulePoolImpl)outputResources).getStringTable());
-        jimageResources.entries().forEach(inResource -> {
-            if (!forgetResources.contains(inResource.getPath())) {
-                ModuleEntry resource = inResource;
-                // Do we have a transformed class with the same name?
-                ModuleEntry res = transformedResources.
-                        get(toJavaBinaryResourceName(inResource.getPath()));
-                if (res != null) {
-                    resource = res;
-                } else {
-                    res = transformedClasses.
-                            get(toJavaBinaryClassName(inResource.getPath()));
-                    if (res != null) {
-                        resource = res;
-                    }
-                }
-                output.add(resource);
-                added.add(resource.getPath());
-            }
-        });
-        // Then new resources
-        for (Map.Entry<String, ModuleEntry> entry : transformedResources.entrySet()) {
-            ModuleEntry resource = entry.getValue();
-            if (!forgetResources.contains(resource.getPath())) {
-                if (!added.contains(resource.getPath())) {
-                    output.add(resource);
-                }
-            }
-        }
-        // And new classes
-        for (Map.Entry<String, ModuleEntry> entry : transformedClasses.entrySet()) {
-            ModuleEntry resource = entry.getValue();
-            if (!forgetResources.contains(resource.getPath())) {
-                if (!added.contains(resource.getPath())) {
-                    output.add(resource);
-                }
-            }
-        }
-
-        AsmPools.sort(outputResources, output, sorter);
-    }
-
-    /**
-     * Associate a package to this module, useful when adding new classes in new
-     * packages. WARNING: In order to properly handle new package and/or new
-     * module, module-info class must be added and/or updated.
-     *
-     * @param pkg The new package, following java binary syntax (/-separated
-     * path name).
-     * @throws PluginException If a mapping already exist for this package.
-     */
-    @Override
-    public void addPackage(String pkg) {
-        Objects.requireNonNull(pkg);
-        Objects.requireNonNull(moduleName);
-        pkg = pkg.replaceAll("/", ".");
-        String mod = newPackageMapping.get(pkg);
-        if (mod != null) {
-            throw new PluginException(mod + " module already contains package " + pkg);
-        }
-        newPackageMapping.put(pkg, moduleName);
-    }
-
-    @Override
-    public Set<String> getAllPackages() {
-        ModuleDescriptor desc = getDescriptor();
-        Set<String> packages = new HashSet<>();
-        for (String p : desc.conceals()) {
-            packages.add(p.replaceAll("\\.", "/"));
-        }
-        for (String p : newPackageMapping.keySet()) {
-            packages.add(p.replaceAll("\\.", "/"));
-        }
-        for (Exports ex : desc.exports()) {
-            packages.add(ex.source().replaceAll("\\.", "/"));
-        }
-        return packages;
-    }
-
-    private static ClassReader newClassReader(byte[] bytes) {
-        try {
-            ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
-            ClassReader reader = new ClassReader(stream);
-            return reader;
-        } catch (IOException ex) {
-            throw new UncheckedIOException(ex);
-        }
-    }
-
-    private static String toJavaBinaryClassName(String path) {
-        if (path.endsWith("module-info.class")) {
-            path = removeClassExtension(path);
-        } else {
-            path = removeModuleName(path);
-            path = removeClassExtension(path);
-        }
-        return path;
-    }
-
-    private static String toJavaBinaryResourceName(String path) {
-        if (!path.endsWith("module-info.class")) {
-            path = removeModuleName(path);
-        }
-        return path;
-    }
-
-    private static String removeClassExtension(String path) {
-        return path.substring(0, path.length() - ".class".length());
-    }
-
-    private static String removeModuleName(String path) {
-        path = path.substring(1);
-        return path.substring(path.indexOf("/") + 1, path.length());
-    }
-
-    private String toClassNamePath(String className) {
-        return toResourceNamePath(className) + ".class";
-    }
-
-    /**
-     * Entry point to manage resource<->module association.
-     */
-    private String toResourceNamePath(String resourceName) {
-        if (!resourceName.startsWith("/")) {
-            resourceName = "/" + resourceName;
-        }
-        String pkg = toPackage(resourceName);
-        String module = inputClassPackageMapping.get(pkg);
-        if (module == null) {
-            module = newPackageMapping.get(pkg);
-            if (module == null) {
-                module = inputOtherPackageMapping.get(pkg);
-                if (module == null) {
-                    throw new PluginException("No module for package" + pkg);
-                }
-            }
-        }
-        return "/" + module + resourceName;
-    }
-
-    private static String toPackage(String path) {
-        if (path.startsWith("/")) {
-            path = path.substring(1);
-        }
-        int i = path.lastIndexOf("/");
-        if (i == -1) {
-            // Default package...
-            return "";
-        }
-        return path.substring(0, i).replaceAll("/", ".");
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/asm/AsmPools.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,497 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.asm;
-
-import java.lang.module.ModuleDescriptor;
-import java.lang.module.ModuleDescriptor.Exports;
-import java.lang.module.ModuleDescriptor.Requires;
-import static java.lang.module.ModuleDescriptor.Requires.Modifier.PUBLIC;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.Sorter;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
-
-/**
- * A container for pools of ClassReader and other resource files. A pool of all
- * the resources or a pool for a given module can be retrieved
- */
-public final class AsmPools {
-
-    /**
-     * Sort the order in which the modules will be stored in the jimage file.
-     */
-    public interface ModuleSorter {
-
-        /**
-         * Sort the list of modules.
-         *
-         * @param modules The list of module names. The module will be stored in
-         * the jimage following this order.
-         * @return A list of module names that expresses the order in which the
-         * modules are stored in the jimage.
-         */
-        public List<String> sort(List<String> modules);
-    }
-
-    private class AsmGlobalPoolImpl implements AsmGlobalPool {
-
-        private Sorter sorter = null;
-
-        private class GlobalWritableClassPool implements WritableClassPool {
-
-            @Override
-            public void addClass(ClassWriter writer) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedClasses().addClass(writer);
-                });
-            }
-
-            @Override
-            public void forgetClass(String className) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedClasses().forgetClass(className);
-                });
-            }
-
-            @Override
-            public ClassReader getClassReader(String binaryName) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedClasses().getClassReader(binaryName);
-                });
-            }
-
-            @Override
-            public Collection<ModuleEntry> getClasses() {
-                List<ModuleEntry> all = new ArrayList<>();
-                visitAllPools((AsmModulePool pool) -> {
-                    for (ModuleEntry rf : pool.getTransformedClasses().getClasses()) {
-                        all.add(rf);
-                    }
-                });
-                return all;
-            }
-
-            @Override
-            public ClassReader getClassReader(ModuleEntry res) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedClasses().getClassReader(res);
-                });
-            }
-
-        }
-
-        private class GlobalWritableResourcePool implements WritableResourcePool {
-
-            @Override
-            public void addResourceFile(ResourceFile resFile) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedResourceFiles().addResourceFile(resFile);
-                });
-            }
-
-            @Override
-            public void forgetResourceFile(String resourceName) {
-                visitFirstNonFailingPool((AsmModulePool pool) -> {
-                    pool.getTransformedResourceFiles().forgetResourceFile(resourceName);
-                });
-            }
-
-            @Override
-            public ResourceFile getResourceFile(String name) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedResourceFiles().getResourceFile(name);
-                });
-            }
-
-            @Override
-            public Collection<ModuleEntry> getResourceFiles() {
-                List<ModuleEntry> all = new ArrayList<>();
-                visitAllPools((AsmModulePool pool) -> {
-                    for (ModuleEntry rf : pool.getTransformedResourceFiles().getResourceFiles()) {
-                        all.add(rf);
-                    }
-                });
-                return all;
-            }
-
-            @Override
-            public ResourceFile getResourceFile(ModuleEntry res) {
-                return visitPools((AsmModulePool pool) -> {
-                    return pool.getTransformedResourceFiles().getResourceFile(res);
-                });
-            }
-
-        }
-
-        @Override
-        public AsmPool.WritableClassPool getTransformedClasses() {
-            return new GlobalWritableClassPool();
-        }
-
-        @Override
-        public AsmPool.WritableResourcePool getTransformedResourceFiles() {
-            return new GlobalWritableResourcePool();
-        }
-
-        @Override
-        public void setSorter(AsmPool.Sorter sorter) {
-            this.sorter = sorter;
-        }
-
-        @Override
-        public Collection<ModuleEntry> getClasses() {
-            List<ModuleEntry> all = new ArrayList<>();
-            visitAllPools((AsmModulePool pool) -> {
-                for (ModuleEntry rf : pool.getClasses()) {
-                    all.add(rf);
-                }
-            });
-            return all;
-        }
-
-        @Override
-        public Collection<ModuleEntry> getResourceFiles() {
-            List<ModuleEntry> all = new ArrayList<>();
-            visitAllPools((AsmModulePool pool) -> {
-                for (ModuleEntry rf : pool.getResourceFiles()) {
-                    all.add(rf);
-                }
-            });
-            return all;
-        }
-
-        @Override
-        public AsmPool.ResourceFile getResourceFile(String binaryName) {
-            return visitPools((AsmModulePool pool) -> {
-                return pool.getResourceFile(binaryName);
-            });
-        }
-
-        @Override
-        public ClassReader getClassReader(String binaryName) {
-            return visitPoolsEx((AsmModulePool pool) -> {
-                return pool.getClassReader(binaryName);
-            });
-        }
-
-        @Override
-        public ResourceFile getResourceFile(ModuleEntry res) {
-            return visitPools((AsmModulePool pool) -> {
-                return pool.getResourceFile(res);
-            });
-        }
-
-        @Override
-        public ClassReader getClassReader(ModuleEntry res) {
-            return visitPoolsEx((AsmModulePool pool) -> {
-                return pool.getClassReader(res);
-            });
-        }
-
-        @Override
-        public void visitClassReaders(AsmPool.ClassReaderVisitor visitor) {
-            visitAllPoolsEx((AsmModulePool pool) -> {
-                pool.visitClassReaders(visitor);
-            });
-        }
-
-        @Override
-        public void visitResourceFiles(AsmPool.ResourceFileVisitor visitor) {
-            visitAllPoolsEx((AsmModulePool pool) -> {
-                pool.visitResourceFiles(visitor);
-            });
-        }
-
-        @Override
-        public void fillOutputResources(ModulePool outputResources) {
-            AsmPools.this.fillOutputResources(outputResources);
-        }
-
-        @Override
-        public void addPackageModuleMapping(String pkg, String module) {
-            AsmModulePool p = pools.get(module);
-            if (p == null) {
-                throw new PluginException("Unknown module " + module);
-            }
-            p.addPackage(pkg);
-        }
-
-        @Override
-        public Set<String> getAccessiblePackages(String module) {
-            AsmModulePool p = pools.get(module);
-            if (p == null) {
-                return null;
-            }
-            ModuleDescriptor desc = p.getDescriptor();
-            Set<String> packages = new HashSet<>();
-            packages.addAll(p.getAllPackages());
-
-            // Retrieve direct dependencies and indirect ones (public)
-            Set<String> modules = new HashSet<>();
-            for (Requires req : desc.requires()) {
-                modules.add(req.name());
-                addAllRequirePublicModules(req.name(), modules);
-            }
-            // Add exported packages of readable modules
-            for (String readable : modules) {
-                AsmModulePool mp = pools.get(readable);
-                if (mp != null) {
-                    for (Exports e : mp.getDescriptor().exports()) {
-                        // exported to all or to the targeted module
-                        if (e.targets().isEmpty() || e.targets().contains(module)) {
-                            packages.add(e.source().replaceAll("\\.", "/"));
-                        }
-                    }
-
-                }
-            }
-            return packages;
-        }
-
-        private void addAllRequirePublicModules(String module, Set<String> modules) {
-            AsmModulePool p = pools.get(module);
-            if (p != null) {
-                for (Requires req : p.getDescriptor().requires()) {
-                    if (req.modifiers().contains(PUBLIC)) {
-                        modules.add(req.name());
-                        addAllRequirePublicModules(req.name(), modules);
-                    }
-                }
-            }
-        }
-
-    }
-
-    private interface VoidPoolVisitor {
-
-        void visit(AsmModulePool pool);
-    }
-
-    private interface VoidPoolVisitorEx {
-
-        void visit(AsmModulePool pool);
-    }
-
-    private interface RetPoolVisitor<P> {
-
-        P visit(AsmModulePool pool);
-    }
-
-    private final Map<String, AsmModulePool> pools = new LinkedHashMap<>();
-    private final AsmModulePool[] poolsArray;
-    private final AsmGlobalPoolImpl global;
-
-    private ModuleSorter moduleSorter;
-
-    /**
-     * A new Asm pools.
-     *
-     * @param inputResources The raw resources to build the pool from.
-     */
-    public AsmPools(ModulePool inputResources) {
-        Objects.requireNonNull(inputResources);
-        Map<String, ModulePool> resPools = new LinkedHashMap<>();
-        Map<String, ModuleDescriptor> descriptors = new HashMap<>();
-        inputResources.entries().forEach(res -> {
-            ModulePool p = resPools.get(res.getModule());
-            if (p == null) {
-                p = new ModulePoolImpl(inputResources.getByteOrder(),
-                        ((ModulePoolImpl)inputResources).getStringTable());
-                resPools.put(res.getModule(), p);
-            }
-            if (res.getPath().endsWith("module-info.class")) {
-                ByteBuffer bb = ByteBuffer.wrap(res.getBytes());
-                ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
-                descriptors.put(res.getModule(), descriptor);
-            }
-            p.add(res);
-        });
-        poolsArray = new AsmModulePool[resPools.size()];
-        int i = 0;
-
-        for (Entry<String, ModulePool> entry : resPools.entrySet()) {
-            ModuleDescriptor descriptor = descriptors.get(entry.getKey());
-            if (descriptor == null) {
-                throw new PluginException("module-info.class not found for " + entry.getKey() + " module");
-            }
-            AsmModulePool p = new AsmPoolImpl(entry.getValue(),
-                    entry.getKey(), this, descriptor);
-            pools.put(entry.getKey(), p);
-            poolsArray[i] = p;
-            i += 1;
-        }
-        global = new AsmGlobalPoolImpl();
-    }
-
-    /**
-     * The pool containing all classes and other resources.
-     *
-     * @return The global pool
-     */
-    public AsmGlobalPool getGlobalPool() {
-        return global;
-    }
-
-    /**
-     * A pool for a given module
-     *
-     * @param name The module name
-     * @return The pool that contains content of the passed module or null if
-     * the module doesn't exist.
-     */
-    public AsmModulePool getModulePool(String name) {
-        Objects.requireNonNull(name);
-        return pools.get(name);
-    }
-
-    /**
-     * The array of module pools.
-     * @return The module pool array.
-     */
-    public AsmModulePool[] getModulePools() {
-        return poolsArray.clone();
-    }
-
-    /**
-     * Set a module sorter. Sorter is used when computing the output resources.
-     *
-     * @param moduleSorter The module sorter
-     */
-    public void setModuleSorter(ModuleSorter moduleSorter) {
-        Objects.requireNonNull(moduleSorter);
-        this.moduleSorter = moduleSorter;
-    }
-
-    /**
-     * Returns the pool of all the resources (transformed and unmodified). The
-     * input resources are replaced by the transformed ones. If a sorter has
-     * been set, it is used to sort in modules.
-     *
-     * @param outputResources The pool used to fill the jimage.
-     */
-    public void fillOutputResources(ModulePool outputResources) {
-        // First sort modules
-        List<String> modules = new ArrayList<>();
-        for (String k : pools.keySet()) {
-            modules.add(k);
-        }
-        if (moduleSorter != null) {
-            modules = moduleSorter.sort(modules);
-        }
-        ModulePool output = new ModulePoolImpl(outputResources.getByteOrder(),
-                ((ModulePoolImpl)outputResources).getStringTable());
-        for (String mn : modules) {
-            AsmPool pool = pools.get(mn);
-            pool.fillOutputResources(output);
-        }
-        sort(outputResources, output, global.sorter);
-    }
-
-    static void sort(ModulePool outputResources,
-            ModulePool transientOutput, Sorter sorter) {
-        if (sorter != null) {
-            List<String> order = sorter.sort(transientOutput);
-            for (String s : order) {
-                outputResources.add(transientOutput.findEntry(s).get());
-            }
-        } else {
-            transientOutput.entries().forEach(res-> {
-                outputResources.add(res);
-            });
-        }
-    }
-
-    private void visitFirstNonFailingPool(VoidPoolVisitorEx pv) {
-        boolean found = false;
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            try {
-                pv.visit(entry.getValue());
-                found = true;
-                break;
-            } catch (Exception ex) {
-                // XXX OK, try  another one.
-            }
-        }
-        if (!found) {
-            throw new PluginException("No module found");
-        }
-    }
-
-    private void visitAllPools(VoidPoolVisitor pv) {
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            pv.visit(entry.getValue());
-        }
-    }
-
-    private void visitAllPoolsEx(VoidPoolVisitorEx pv) {
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            pv.visit(entry.getValue());
-        }
-    }
-
-    private <P> P visitPoolsEx(RetPoolVisitor<P> pv) {
-        P p = null;
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            try {
-                p = pv.visit(entry.getValue());
-                if (p != null) {
-                    break;
-                }
-            } catch (Exception ex) {
-                // XXX OK, try  another one.
-            }
-        }
-        return p;
-    }
-
-    private <P> P visitPools(RetPoolVisitor<P> pv) {
-        P p = null;
-        for (Entry<String, AsmModulePool> entry : pools.entrySet()) {
-            try {
-                p = pv.visit(entry.getValue());
-                if (p != null) {
-                    break;
-                }
-            } catch (Exception ex) {
-                // XXX OK, try  another one.
-            }
-        }
-        return p;
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ControlFlow.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,516 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.optim;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Objects;
-import java.util.Set;
-import java.util.Stack;
-import java.util.TreeSet;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.analysis.Analyzer;
-import jdk.internal.org.objectweb.asm.tree.analysis.AnalyzerException;
-import jdk.internal.org.objectweb.asm.tree.analysis.BasicInterpreter;
-import jdk.internal.org.objectweb.asm.tree.analysis.BasicValue;
-
-/**
- * Split Java method onto a control flow.
- *
- */
-public final class ControlFlow {
-
-    /**
-     * A block of control
-     */
-    public static final class Block implements Comparable<Block> {
-
-        private final InstructionNode firstInstruction;
-        private final List<InstructionNode> instr = new ArrayList<>();
-        private final List<Block> reachable = new ArrayList<>();
-        private final List<Block> exceptionHandlers = new ArrayList<>();
-        private boolean isExceptionHandler;
-
-        private Block(InstructionNode firstInstruction) {
-            this.firstInstruction = firstInstruction;
-        }
-
-        @Override
-        public boolean equals(Object other) {
-            if (!(other instanceof Block)) {
-                return false;
-            }
-            Block b = (Block) other;
-            return firstInstruction.equals(b.firstInstruction);
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hashCode(this.firstInstruction);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder();
-            for (InstructionNode in : instr) {
-                builder.append(in).append(" ");
-            }
-            builder.append(" reachables: ");
-            for (Block r : reachable) {
-                builder.append(r.getFirstInstruction()).append(" ");
-            }
-            builder.append(" exception handlers: ");
-            for (Block r : exceptionHandlers) {
-                builder.append(r.getFirstInstruction()).append(" ");
-            }
-
-            return "block[" + getFirstInstruction() + "],ex:"
-                    + isExceptionHandler + ",  " + builder.toString();
-        }
-
-        /**
-         * @return the firstInstruction
-         */
-        public InstructionNode getFirstInstruction() {
-            return firstInstruction;
-        }
-
-        /**
-         * @return the instr
-         */
-        public List<InstructionNode> getInstructions() {
-            return Collections.unmodifiableList(instr);
-        }
-
-        /**
-         * @return the reachable
-         */
-        public List<Block> getReachableBlocks() {
-            return Collections.unmodifiableList(reachable);
-        }
-
-        /**
-         * @return the exceptionHandlers
-         */
-        public List<Block> getExceptionHandlerBlocks() {
-            return Collections.unmodifiableList(exceptionHandlers);
-        }
-
-        @Override
-        public int compareTo(Block t) {
-            return this.firstInstruction.index - t.firstInstruction.index;
-        }
-
-        public boolean isExceptionHandler() {
-            return isExceptionHandler;
-        }
-
-    }
-
-    private class ClosureBuilder {
-
-        private final Block root;
-
-        private ClosureBuilder(Block root) {
-            Objects.requireNonNull(root);
-            this.root = root;
-        }
-
-        private Set<Block> build() {
-            Set<Block> allReachable = new TreeSet<>();
-            addAll(root, allReachable);
-            // filter out the reachable from outside this graph
-            Iterator<Block> it = allReachable.iterator();
-            Set<Block> toExclude = new HashSet<>();
-            while (it.hasNext()) {
-                Block b = it.next();
-                for (Block ref : blocks) {
-                    if (!allReachable.contains(ref) && ref.reachable.contains(b)) {
-                        addAll(b, toExclude);
-                        break;
-                    }
-                }
-            }
-            //System.err.println("TO EXCLUDE:\n " + toExclude);
-            allReachable.removeAll(toExclude);
-            //System.err.println("CLOSURE:\n " + allReachable);
-            return Collections.unmodifiableSet(allReachable);
-        }
-
-        // Compute the set of blocks reachable from the current block
-        private void addAll(Block current, Set<Block> closure) {
-            Objects.requireNonNull(current);
-            closure.add(current);
-            for (Block ex : current.exceptionHandlers) {
-                Objects.requireNonNull(ex);
-                if (!closure.contains(ex)) {
-                    addAll(ex, closure);
-                }
-            }
-            for (Block r : current.reachable) {
-                Objects.requireNonNull(r);
-                if (!closure.contains(r)) {
-                    addAll(r, closure);
-                }
-            }
-
-        }
-    }
-
-    /**
-     * An instruction
-     */
-    public static final class InstructionNode {
-
-        private final int index;
-        private final List<InstructionNode> next = new ArrayList<>();
-        private final AbstractInsnNode instr;
-
-        private InstructionNode(int index, AbstractInsnNode instr) {
-            this.index = index;
-            this.instr = instr;
-        }
-
-        @Override
-        public boolean equals(Object obj) {
-            if (!(obj instanceof InstructionNode)) {
-                return false;
-            }
-            final InstructionNode other = (InstructionNode) obj;
-            return this.getIndex() == other.getIndex();
-        }
-
-        @Override
-        public int hashCode() {
-            return this.getIndex();
-        }
-
-        @Override
-        public String toString() {
-            return getIndex() + "(" + (getInstr().getOpcode() == - 1 ? -1
-                    : Integer.toHexString(getInstr().getOpcode())) + ")";
-        }
-
-        /**
-         * @return the index
-         */
-        public int getIndex() {
-            return index;
-        }
-
-        /**
-         * @return the instr
-         */
-        public AbstractInsnNode getInstr() {
-            return instr;
-        }
-
-    }
-
-    private final Map<Integer, Block> allBlocks;
-    private final List<Block> blocks = new ArrayList<>();
-
-    private ControlFlow(Map<Integer, Block> allBlocks) {
-        this.allBlocks = allBlocks;
-        for (Block b : allBlocks.values()) {
-            blocks.add(b);
-        }
-        Collections.sort(blocks);
-    }
-
-    public List<Block> getBlocks() {
-
-        return Collections.unmodifiableList(blocks);
-    }
-
-    public Block getBlock(int firstInstr) {
-        return allBlocks.get(firstInstr);
-    }
-
-    public static ControlFlow createControlFlow(String owner,
-            MethodNode method) throws Exception {
-
-        BlockBuilder bb = new BlockBuilder(owner, method);
-        return bb.build();
-    }
-
-    /**
-     * Return the set of blocks that are only reachable from this block For
-     * example, if b is an Exception handler, returns all the blocks reachable
-     * only from this handler
-     *
-     * @param b
-     * @return
-     */
-    public Set<Block> getClosure(Block b) {
-        return new ClosureBuilder(b).build();
-    }
-
-    private static final class BlockBuilder {
-
-        private InstructionNode root;
-        private final Map<Integer, InstructionNode> instructions = new HashMap<>();
-        private final Map<Integer, List<Integer>> handlers = new HashMap<>();
-        private final Map<Integer, Block> allBlocks = new HashMap<>();
-
-        private final String owner;
-        private final MethodNode method;
-
-        private BlockBuilder(String owner, MethodNode method) {
-            this.owner = owner;
-            this.method = method;
-        }
-
-        private void analyze() throws AnalyzerException {
-            Analyzer<BasicValue> analyzer = new Analyzer<BasicValue>(new BasicInterpreter()) {
-
-                @Override
-                protected boolean newControlFlowExceptionEdge(int insn,
-                        int successor) {
-                    List<Integer> lst = handlers.get(successor);
-                    if (lst == null) {
-                        lst = new ArrayList<>();
-                        handlers.put(successor, lst);
-                    }
-                    lst.add(insn);
-                    return true;
-                }
-
-                @Override
-                protected void newControlFlowEdge(int from,
-                        int to) {
-                    if (root == null) {
-                        root = new InstructionNode(from, method.instructions.get(from));
-                        instructions.put(from, root);
-                    }
-                    InstructionNode fromNode = instructions.get(from);
-                    if (fromNode == null) {
-                        fromNode = new InstructionNode(from, method.instructions.get(from));
-                        instructions.put(from, fromNode);
-                    }
-                    InstructionNode toNode = instructions.get(to);
-                    if (toNode == null) {
-                        toNode = new InstructionNode(to, method.instructions.get(to));
-                        instructions.put(to, toNode);
-                    }
-                    if (!fromNode.next.contains(toNode)) {
-                        fromNode.next.add(toNode);
-                    }
-
-                }
-            };
-            analyzer.analyze(owner, method);
-        }
-
-        private Block newBlock(InstructionNode firstInstruction) {
-            Objects.requireNonNull(firstInstruction);
-            Block b = new Block(firstInstruction);
-            allBlocks.put(firstInstruction.getIndex(), b);
-            return b;
-        }
-
-        private ControlFlow build() throws AnalyzerException {
-            analyze();
-            buildBlocks();
-            return new ControlFlow(allBlocks);
-        }
-
-        private void buildBlocks() {
-            List<Block> reachableBlocks = new ArrayList<>();
-            createBlocks(root, reachableBlocks);
-            List<Block> handlersBlocks = new ArrayList<>();
-            for (Entry<Integer, List<Integer>> entry : handlers.entrySet()) {
-                InstructionNode node = instructions.get(entry.getKey());
-                createBlocks(node, handlersBlocks);
-            }
-
-            // attach handler to try blocks
-            for (Entry<Integer, List<Integer>> entry : handlers.entrySet()) {
-                Block handlerBlock = allBlocks.get(entry.getKey());
-                handlerBlock.isExceptionHandler = true;
-                int startTry = entry.getValue().get(0);
-                Block tryBlock = allBlocks.get(startTry);
-                if (tryBlock == null) {
-                    // Need to find the block that contains the instruction and
-                    // make a new block
-                    Block split = null;
-                    for (Block b : allBlocks.values()) {
-                        Iterator<InstructionNode> it = b.instr.iterator();
-                        while (it.hasNext()) {
-                            InstructionNode in = it.next();
-                            if (split == null) {
-                                if (in.index == startTry) {
-                                    split = newBlock(in);
-                                    split.instr.add(in);
-                                    it.remove();
-                                }
-                            } else {
-                                split.instr.add(in);
-                                it.remove();
-                            }
-                        }
-                        if (split != null) {
-                            Iterator<Block> reachables = b.reachable.iterator();
-                            while (reachables.hasNext()) {
-                                Block r = reachables.next();
-                                split.reachable.add(r);
-                                reachables.remove();
-                            }
-                            b.reachable.add(split);
-                            break;
-                        }
-                    }
-                    if (split == null) {
-                        throw new RuntimeException("No try block for handler " + handlerBlock);
-                    }
-                    split.exceptionHandlers.add(handlerBlock);
-                } else {
-                    tryBlock.exceptionHandlers.add(handlerBlock);
-                }
-            }
-
-//            System.err.println("ALL BLOCKS FOUND");
-//            Iterator<Entry<Integer, Block>> blockIt0 = allBlocks.entrySet().iterator();
-//            while (blockIt0.hasNext()) {
-//                Block b = blockIt0.next().getValue();
-//                System.err.println(b);
-//            }
-            //compute real exception blocks, if an instruction is in another block, stop.
-            Iterator<Entry<Integer, Block>> blockIt = allBlocks.entrySet().iterator();
-            while (blockIt.hasNext()) {
-                Block b = blockIt.next().getValue();
-                Iterator<InstructionNode> in = b.instr.iterator();
-                boolean found = false;
-                while (in.hasNext()) {
-                    int i = in.next().getIndex();
-                    if (found) {
-                        in.remove();
-                    } else {
-                        if (startsWith(b, i, allBlocks.values())) {
-                            // Move it to reachable
-                            Block r = allBlocks.get(i);
-                            b.reachable.add(r);
-                            found = true;
-                            in.remove();
-                        } else {
-                        }
-                    }
-                }
-            }
-
-//            System.err.println("Reduced blocks");
-//            Iterator<Entry<Integer, Block>> blockIt1 = allBlocks.entrySet().iterator();
-//            while (blockIt1.hasNext()) {
-//                Block b = blockIt1.next().getValue();
-//                System.err.println(b);
-//            }
-        }
-
-        private boolean startsWith(Block block, int index, Collection<Block> reachableBlocks) {
-            for (Block b : reachableBlocks) {
-                if (b != block && !b.instr.isEmpty() && b.instr.get(0).getIndex() == index) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private static final class StackItem {
-
-            private final InstructionNode instr;
-            private final Block currentBlock;
-
-            private StackItem(InstructionNode instr, Block currentBlock) {
-                Objects.requireNonNull(instr);
-                Objects.requireNonNull(currentBlock);
-                this.instr = instr;
-                this.currentBlock = currentBlock;
-            }
-        }
-
-        /**
-         * This algorithm can't be recursive, possibly too much instructions in
-         * methods.
-         */
-        private void createBlocks(InstructionNode root, List<Block> blocks) {
-            final Stack<StackItem> stack = new Stack<>();
-            stack.push(new StackItem(root, newBlock(root)));
-            while (!stack.isEmpty()) {
-                final StackItem item = stack.pop();
-                final Block currentBlock = item.currentBlock;
-                final InstructionNode current = item.instr;
-                // loop
-                if (currentBlock.instr.contains(current)) {
-                    currentBlock.reachable.add(currentBlock);
-                    continue;
-                }
-                Block existing = allBlocks.get(current.index);
-                if (existing != null && existing != currentBlock) {
-                    currentBlock.reachable.add(existing);
-                    continue;
-                }
-                int previous = currentBlock.instr.size() > 0
-                        ? currentBlock.instr.get(currentBlock.instr.size() - 1).getIndex() : -1;
-                if (previous == -1 || current.getIndex() == previous + 1) {
-                    currentBlock.instr.add(current);
-                    if (current.next.isEmpty()) {
-                        blocks.add(currentBlock);
-                    } else {
-                        if (current.next.size() > 1) {
-                            blocks.add(currentBlock);
-                            for (InstructionNode n : current.next) {
-                                Block loop = allBlocks.get(n.index);
-                                if (loop == null) {
-                                    Block newBlock = newBlock(n);
-                                    currentBlock.reachable.add(newBlock);
-                                    stack.push(new StackItem(n, newBlock));
-                                } else { // loop
-                                    currentBlock.reachable.add(loop);
-                                }
-                            }
-                        } else {
-                            stack.push(new StackItem(current.next.get(0),
-                                    currentBlock));
-                        }
-                    }
-                } else { // to a new block...
-                    // Do nothing...
-                    blocks.add(currentBlock);
-                    Block newBlock = newBlock(current);
-                    currentBlock.reachable.add(newBlock);
-                    stack.push(new StackItem(current, newBlock));
-                }
-            }
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ForNameFolding.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.optim;
-
-import java.io.IOException;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.function.Consumer;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.tools.jlink.internal.plugins.OptimizationPlugin.MethodOptimizer;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
-import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.Data;
-import jdk.tools.jlink.internal.plugins.optim.ReflectionOptimizer.TypeResolver;
-
-
-/**
- * MethodOptimizer that removes Class.forName when possible.
- * WARNING: This code is experimental.
- * TODO: Need to check that the type is accessible prior to replace with a constant.
- */
-public class ForNameFolding implements MethodOptimizer {
-
-    private int numNotReplaced;
-    private int numReplacement;
-    private int numRemovedHandlers;
-    private int instructionsRemoved;
-
-    private Consumer<String> logger;
-
-    @Override
-    public boolean optimize(Consumer<String> logger, AsmPools pools,
-            AsmModulePool modulePool,
-            ClassNode cn, MethodNode m, TypeResolver resolver) throws Exception {
-        this.logger = logger;
-        Data data = ReflectionOptimizer.replaceWithClassConstant(cn, m, createResolver(resolver));
-        instructionsRemoved += data.removedInstructions();
-        numRemovedHandlers += data.removedHandlers().size();
-        for (Entry<String, Set<Block>> entry : data.removedHandlers().entrySet()) {
-            logRemoval(cn.name + "." + m.name + "removed block for " + entry.getKey()
-                    + " : " + entry.getValue());
-        }
-        return data.removedInstructions() > 0;
-    }
-
-    public TypeResolver createResolver(TypeResolver resolver) {
-        return (ClassNode cn, MethodNode mn, String type) -> {
-            ClassReader reader = resolver.resolve(cn, mn, type);
-            if (reader == null) {
-                logNotReplaced(type);
-            } else {
-                logReplaced(type);
-            }
-            return reader;
-        };
-    }
-
-    private void logReplaced(String type) {
-        numReplacement += 1;
-    }
-
-    private void logNotReplaced(String type) {
-        numNotReplaced += 1;
-        if (logger != null) {
-            logger.accept(type + " not resolved");
-        }
-    }
-
-    private void logRemoval(String content) {
-        numRemovedHandlers += 1;
-        if (logger != null) {
-            logger.accept(content);
-        }
-    }
-
-    @Override
-    public void close() throws IOException {
-        if (logger != null) {
-            logger.accept("Class.forName Folding results:\n " + numReplacement
-                    + " removed reflection. " + numRemovedHandlers
-                    + " removed exception handlers."
-                    + numNotReplaced + " types unknown. "
-                    + instructionsRemoved + " instructions removed\n");
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/ReflectionOptimizer.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,226 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.optim;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.IdentityHashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.Type;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.LabelNode;
-import jdk.internal.org.objectweb.asm.tree.LdcInsnNode;
-import jdk.internal.org.objectweb.asm.tree.LineNumberNode;
-import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
-import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
-
-/**
- * Implement the reflection optimization.
- */
-public class ReflectionOptimizer {
-
-    public static class Data {
-
-        private int removedInstructions;
-        private final Map<String, Set<Block>> removedHandlers = new HashMap<>();
-
-        private Data() {
-        }
-
-        public int removedInstructions() {
-            return removedInstructions;
-        }
-
-        public Map<String, Set<Block>> removedHandlers() {
-            return Collections.unmodifiableMap(removedHandlers);
-        }
-    }
-
-    public interface TypeResolver {
-
-        public ClassReader resolve(ClassNode cn, MethodNode m, String type);
-    }
-
-    public static Data replaceWithClassConstant(ClassNode cn, MethodNode m,
-            TypeResolver cch)
-            throws Exception {
-        Iterator<AbstractInsnNode> it = m.instructions.iterator();
-        LdcInsnNode insNode = null;
-        Map<LdcInsnNode, LdcInsnNode> replacement = new IdentityHashMap<>();
-        Data data = new Data();
-        while (it.hasNext()) {
-            AbstractInsnNode n = it.next();
-            if (n instanceof LdcInsnNode) {
-                LdcInsnNode ldc = (LdcInsnNode) n;
-                if (ldc.cst instanceof String) {
-                    insNode = ldc;
-                }
-            } else {
-                if (n instanceof MethodInsnNode && insNode != null) {
-                    MethodInsnNode met = (MethodInsnNode) n;
-                    if (met.name.equals("forName")
-                            && met.owner.equals("java/lang/Class")
-                            && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
-                        // Can we load the type?
-                        Type type = null;
-                        String binaryName = insNode.cst.toString().replaceAll("\\.", "/");
-                        String unaryClassName = binaryName;
-                        int arrayIndex = binaryName.lastIndexOf("[");
-                        if (arrayIndex >= 0) {
-                            int objIndex = unaryClassName.indexOf("L");
-                            if (objIndex >= 0) {
-                                unaryClassName = unaryClassName.substring(objIndex + 1);
-                                unaryClassName = unaryClassName.substring(0,
-                                        unaryClassName.length() - 1);
-                            } else {
-                                //primitive, this is just fine.
-                                type = Type.getObjectType(binaryName);
-                            }
-                        }
-                        if (type == null) {
-                            if (cch.resolve(cn, m, unaryClassName) != null) {
-                                type = Type.getObjectType(binaryName);
-                            }
-                        }
-                        if (type != null) {
-                            replacement.put(insNode, new LdcInsnNode(type));
-                            it.remove();
-                            data.removedInstructions += 1;
-                        }
-                    } else {
-                        insNode = null;
-                    }
-                    // Virtual node, not taken into account
-                } else if (!(n instanceof LabelNode) && !(n instanceof LineNumberNode)) {
-                    insNode = null;
-                }
-            }
-        }
-        for (Map.Entry<LdcInsnNode, LdcInsnNode> entry : replacement.entrySet()) {
-            m.instructions.set(entry.getKey(), entry.getValue());
-        }
-        if (!replacement.isEmpty()) {
-            String[] types = {"java/lang/ClassNotFoundException"};
-            data.removedInstructions += deleteExceptionHandlers(cch, data, cn, m, types);
-
-        }
-        return data;
-    }
-
-    private static int deleteExceptionHandlers(TypeResolver cch, Data data,
-            ClassNode cn, MethodNode m, String[] exTypes)
-            throws Exception {
-        int instructionsRemoved = 0;
-        for (String ex : exTypes) {
-            ControlFlow f = ControlFlow.createControlFlow(cn.name, m);
-            List<Integer> removed = new ArrayList<>();
-            Set<ControlFlow.Block> blocksToRemove = new TreeSet<>();
-            Iterator<TryCatchBlockNode> it = m.tryCatchBlocks.iterator();
-            List<TryCatchBlockNode> tcbToRemove = new ArrayList<>();
-            while (it.hasNext()) {
-                TryCatchBlockNode bn = it.next();
-                if (bn.type == null
-                        || !bn.type.equals(ex) // An empty block
-                        || tcbToRemove.contains(bn)) {
-                    continue;
-                }
-                // Check that the handler is still required
-                if (!Utils.canThrowCheckedException(cch, cn, m, bn)) {
-                    // try to suppress it.
-                    int block = m.instructions.indexOf(bn.handler);
-                    ControlFlow.Block blockHandler = f.getBlock(block);
-                    if (blockHandler == null) {
-                        if (removed.contains(block)) {
-                            continue;
-                        } else {
-                            throw new Exception(cn.name
-                                    + ", no block for handler " + block);
-                        }
-                    }
-                    tcbToRemove.add(bn);
-                    // Don't delete block if shared (eg: ClassNotFoundException | NoSuchMethodException |
-                    Iterator<TryCatchBlockNode> it2 = m.tryCatchBlocks.iterator();
-                    boolean cont = false;
-                    while (it2.hasNext()) {
-                        TryCatchBlockNode bn2 = it2.next();
-                        if (bn2 != bn) {
-                            if (bn2.start.equals(bn.start)) {
-                                cont = true;
-                            }
-                        }
-                    }
-                    if (cont) {
-                        continue;
-                    }
-                    // An handler is a root, blocks that are only reachable by it
-                    // can be removed.
-                    Set<ControlFlow.Block> blocks = f.getClosure(blockHandler);
-                    StringBuilder sb = new StringBuilder();
-                    for (ControlFlow.Block b : blocks) {
-                        sb.append(b).append("\n");
-                        removed.add(b.getFirstInstruction().getIndex());
-                        // Remove Exception handler if the associated block has been removed
-                        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
-                            if (tcb != bn) {
-                                // An exception handler removed as a side effect.
-                                if (b.isExceptionHandler()
-                                        && b.getFirstInstruction().getInstr() == tcb.handler) {
-                                    tcbToRemove.add(tcb);
-                                }
-                            }
-                        }
-                    }
-                    blocksToRemove.addAll(blocks);
-
-                    data.removedHandlers.put(ex, blocks);
-
-                }
-            }
-
-            m.tryCatchBlocks.removeAll(tcbToRemove);
-
-            if (!blocksToRemove.isEmpty()) {
-                for (ControlFlow.Block b : blocksToRemove) {
-                    for (ControlFlow.InstructionNode ins : b.getInstructions()) {
-                        if (ins.getInstr().getOpcode() > 0) {
-                            instructionsRemoved += 1;
-                        }
-                    }
-                }
-                Utils.suppressBlocks(m, blocksToRemove);
-            }
-        }
-        return instructionsRemoved;
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/internal/plugins/optim/Utils.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,97 +0,0 @@
-/*
- * Copyright (c) 2015, 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.plugins.optim;
-
-import java.util.Iterator;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
-
-/**
- * Optimization utility methods
- */
-public class Utils {
-
-    public static boolean canThrowCheckedException(ReflectionOptimizer.TypeResolver cch,
-            ClassNode classNode, MethodNode m, TryCatchBlockNode bn) throws Exception {
-        int istart = m.instructions.indexOf(bn.start);
-        int iend = m.instructions.indexOf(bn.end);
-        for (int i = istart; i < iend - 1; i++) {
-            AbstractInsnNode instr = m.instructions.get(i);
-            if (instr instanceof MethodInsnNode) {
-                MethodInsnNode meth = (MethodInsnNode) instr;
-                ClassReader reader = cch.resolve(classNode, m, meth.owner);
-                if (reader != null) {
-                    ClassNode cn = new ClassNode();
-                    reader.accept(cn, ClassReader.EXPAND_FRAMES);
-                    for (MethodNode method : cn.methods) {
-                        if (method.name.equals(meth.name)) {
-                            for (String e : method.exceptions) {
-                                if (e.equals(bn.type)) {
-                                    return true;
-                                }
-                            }
-                        }
-                    }
-                } else {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    public static void suppressBlocks(MethodNode m, Set<ControlFlow.Block> toRemove) throws Exception {
-        m.instructions.resetLabels();
-        Iterator<AbstractInsnNode> it = m.instructions.iterator();
-        while (it.hasNext()) {
-            AbstractInsnNode n = it.next();
-            Iterator<TryCatchBlockNode> handlers = m.tryCatchBlocks.iterator();
-            boolean cont = false;
-            // Do not delete instructions that are end of other try block.
-            while (handlers.hasNext()) {
-                TryCatchBlockNode handler = handlers.next();
-                if (handler.end == n) {
-                    cont = true;
-                }
-            }
-            if (cont) {
-                continue;
-            }
-
-            for (ControlFlow.Block b : toRemove) {
-                for (ControlFlow.InstructionNode ins : b.getInstructions()) {
-                    if (ins.getInstr() == n) {
-                        it.remove();
-                    }
-                }
-            }
-        }
-    }
-}
--- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Thu Jul 07 17:53:55 2016 +0900
+++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties	Thu Jul 07 09:38:33 2016 -0300
@@ -31,11 +31,10 @@
 Any number of <key>=<value> pairs can be passed.\n\
 del: is to delete the list of keys in release file.
 
-class-optim.argument=<all|forName-folding>[:log=<log file>]
+class-for-name.argument=
 
-class-optim.description=\
-Class optimization. Warning: This plugin is experimental.\n\
-An optional <log file> can be specified to log applied optimizations.
+class-for-name.description=\
+Class optimization: convert Class.forName calls to constant loads.
 
 compress.argument=<0|1|2>[:filter=<pattern-list>]
 
@@ -47,7 +46,6 @@
 An optional <pattern-list> filter can be specified to list the pattern of\n\
 files to be included.
 
-
 compact-cp.argument=<resource paths>
 
 compact-cp.description=Constant Pool strings sharing.\n\
--- a/src/jdk.jlink/share/classes/module-info.java	Thu Jul 07 17:53:55 2016 +0900
+++ b/src/jdk.jlink/share/classes/module-info.java	Thu Jul 07 09:38:33 2016 -0300
@@ -39,9 +39,9 @@
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.StripNativeCommandsPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OrderResourcesPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
-    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.OptimizationPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ExcludeVMPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.IncludeLocalesPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.GenerateJLIClassesPlugin;
     provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ReleaseInfoPlugin;
-}
+    provides jdk.tools.jlink.plugin.Plugin with jdk.tools.jlink.internal.plugins.ClassForNamePlugin;
+ }
--- a/test/tools/jlink/JLinkOptimTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,354 +0,0 @@
-
-import java.lang.reflect.Method;
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Stream;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.internal.org.objectweb.asm.tree.AbstractInsnNode;
-import jdk.internal.org.objectweb.asm.tree.ClassNode;
-import jdk.internal.org.objectweb.asm.tree.MethodInsnNode;
-import jdk.internal.org.objectweb.asm.tree.MethodNode;
-import jdk.internal.org.objectweb.asm.tree.TryCatchBlockNode;
-import jdk.tools.jlink.internal.PluginRepository;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.internal.plugins.OptimizationPlugin;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.internal.plugins.optim.ControlFlow;
-import jdk.tools.jlink.internal.plugins.optim.ControlFlow.Block;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-import tests.Helper;
-import tests.JImageGenerator;
-
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
- /*
- * @test
- * @summary Test image creation with class optimization
- * @author Jean-Francois Denise
- * @library ../lib
- * @modules java.base/jdk.internal.jimage
- *          jdk.jdeps/com.sun.tools.classfile
- *          jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jmod
- *          jdk.jlink/jdk.tools.jimage
- *          jdk.jlink/jdk.tools.jlink.internal.plugins
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.optim
- *          java.base/jdk.internal.org.objectweb.asm
- *          java.base/jdk.internal.org.objectweb.asm.tree
- *          java.base/jdk.internal.org.objectweb.asm.util
- *          jdk.compiler
- * @build tests.*
- * @run main JLinkOptimTest
- */
-public class JLinkOptimTest {
-
-    private static final String EXPECTED = "expected";
-    private static Helper helper;
-
-    public static class ControlFlowPlugin extends AsmPlugin {
-
-        private boolean called;
-        private int numMethods;
-        private int numBlocks;
-
-        private static final String NAME = "test-optim";
-
-        private ControlFlowPlugin() {
-        }
-
-        @Override
-        public void visit(AsmPools pools) {
-            called = true;
-            for (AsmModulePool p : pools.getModulePools()) {
-
-                p.visitClassReaders((reader) -> {
-                    ClassNode cn = new ClassNode();
-                    if ((reader.getAccess() & Opcodes.ACC_INTERFACE) == 0) {
-                        reader.accept(cn, ClassReader.EXPAND_FRAMES);
-                        for (MethodNode m : cn.methods) {
-                            if ((m.access & Opcodes.ACC_ABSTRACT) == 0
-                                    && (m.access & Opcodes.ACC_NATIVE) == 0) {
-                                numMethods += 1;
-                                try {
-                                    ControlFlow f
-                                            = ControlFlow.createControlFlow(cn.name, m);
-                                    for (Block b : f.getBlocks()) {
-                                        numBlocks += 1;
-                                        f.getClosure(b);
-                                    }
-                                } catch (Throwable ex) {
-                                    //ex.printStackTrace();
-                                    throw new RuntimeException("Exception in "
-                                            + cn.name + "." + m.name, ex);
-                                }
-                            }
-                        }
-                    }
-                    return null;
-                });
-            }
-        }
-
-        @Override
-        public String getName() {
-            return NAME;
-        }
-    }
-
-    private static void testForName() throws Exception {
-        String moduleName = "optimplugin";
-        Path src = Paths.get(System.getProperty("test.src")).resolve(moduleName);
-        Path classes = helper.getJmodClassesDir().resolve(moduleName);
-        JImageGenerator.compile(src, classes);
-
-        FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-        Path root = fs.getPath("/modules/java.base");
-        // Access module-info.class to be reused as fake module-info.class
-        List<ModuleEntry> javabaseResources = new ArrayList<>();
-        try (Stream<Path> stream = Files.walk(root)) {
-            for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext();) {
-                Path p = iterator.next();
-                if (Files.isRegularFile(p)) {
-                    try {
-                        javabaseResources.add(ModuleEntry.create(p.toString().
-                                substring("/modules".length()), Files.readAllBytes(p)));
-                    } catch (Exception ex) {
-                        throw new RuntimeException(ex);
-                    }
-                }
-            }
-        }
-
-        //forName folding
-        ModulePoolImpl pool = new ModulePoolImpl();
-        byte[] content = Files.readAllBytes(classes.
-                resolve("optim").resolve("ForNameTestCase.class"));
-        byte[] content2 = Files.readAllBytes(classes.
-                resolve("optim").resolve("AType.class"));
-        byte[] mcontent = Files.readAllBytes(classes.resolve("module-info.class"));
-
-        pool.add(ModuleEntry.create("/optimplugin/optim/ForNameTestCase.class", content));
-        pool.add(ModuleEntry.create("/optimplugin/optim/AType.class", content2));
-        pool.add(ModuleEntry.create("/optimplugin/module-info.class", mcontent));
-
-        for (ModuleEntry r : javabaseResources) {
-            pool.add(r);
-        }
-
-        OptimizationPlugin plugin = new OptimizationPlugin();
-        Map<String, String> optional = new HashMap<>();
-        optional.put(OptimizationPlugin.NAME, OptimizationPlugin.FORNAME_REMOVAL);
-        optional.put(OptimizationPlugin.LOG, "forName.log");
-        plugin.configure(optional);
-        ModulePool out = new ModulePoolImpl();
-        plugin.visit(pool, out);
-
-        ModuleEntry result = out.entries().iterator().next();
-
-        ClassReader optimReader = new ClassReader(result.getBytes());
-        ClassNode optimClass = new ClassNode();
-        optimReader.accept(optimClass, ClassReader.EXPAND_FRAMES);
-
-        if (!optimClass.name.equals("optim/ForNameTestCase")) {
-            throw new Exception("Invalid class " + optimClass.name);
-        }
-        if (optimClass.methods.size() < 2) {
-            throw new Exception("Not enough methods in new class");
-        }
-        for (MethodNode mn : optimClass.methods) {
-            if (!mn.name.contains("forName") && !mn.name.contains("<clinit>")) {
-                continue;
-            }
-            if (mn.name.startsWith("negative")) {
-                checkForName(mn);
-            } else {
-                checkNoForName(mn);
-            }
-        }
-        Map<String, byte[]> newClasses = new HashMap<>();
-        newClasses.put("optim.ForNameTestCase", result.getBytes());
-        newClasses.put("optim.AType", content2);
-        MemClassLoader loader = new MemClassLoader(newClasses);
-        Class<?> loaded = loader.loadClass("optim.ForNameTestCase");
-        if (loaded.getDeclaredMethods().length < 2) {
-            throw new Exception("Not enough methods in new class");
-        }
-        for (Method m : loaded.getDeclaredMethods()) {
-            if (m.getName().contains("Exception")) {
-                try {
-                    m.invoke(null);
-                } catch (Exception ex) {
-                    //ex.getCause().printStackTrace();
-                    if (!ex.getCause().getMessage().equals(EXPECTED)) {
-                        throw new Exception("Unexpected exception " + ex);
-                    }
-                }
-            } else if (!m.getName().startsWith("negative")) {
-                Class<?> clazz = (Class<?>) m.invoke(null);
-                if (clazz != String.class && clazz != loader.findClass("optim.AType")) {
-                    throw new Exception("Invalid class " + clazz);
-                }
-            }
-        }
-    }
-
-    private static void checkNoForName(MethodNode m) throws Exception {
-        Iterator<AbstractInsnNode> it = m.instructions.iterator();
-        while (it.hasNext()) {
-            AbstractInsnNode n = it.next();
-            if (n instanceof MethodInsnNode) {
-                MethodInsnNode met = (MethodInsnNode) n;
-                if (met.name.equals("forName")
-                        && met.owner.equals("java/lang/Class")
-                        && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
-                    throw new Exception("forName not removed in " + m.name);
-                }
-            }
-        }
-        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
-            if (tcb.type.equals(ClassNotFoundException.class.getName().replaceAll("\\.", "/"))) {
-                throw new Exception("ClassNotFoundException Block not removed for " + m.name);
-            }
-        }
-    }
-
-    private static void checkForName(MethodNode m) throws Exception {
-        Iterator<AbstractInsnNode> it = m.instructions.iterator();
-        boolean found = false;
-        while (it.hasNext()) {
-            AbstractInsnNode n = it.next();
-            if (n instanceof MethodInsnNode) {
-                MethodInsnNode met = (MethodInsnNode) n;
-                if (met.name.equals("forName")
-                        && met.owner.equals("java/lang/Class")
-                        && met.desc.equals("(Ljava/lang/String;)Ljava/lang/Class;")) {
-                    found = true;
-                    break;
-                }
-            }
-        }
-        if (!found) {
-            throw new Exception("forName removed but shouldn't have");
-        }
-        found = false;
-        for (TryCatchBlockNode tcb : m.tryCatchBlocks) {
-            if (tcb.type.equals(ClassNotFoundException.class.getName().replaceAll("\\.", "/"))) {
-                found = true;
-                break;
-            }
-        }
-        if (!found) {
-            throw new Exception("tryCatchBlocks removed but shouldn't have");
-        }
-    }
-
-    static class MemClassLoader extends ClassLoader {
-
-        private final Map<String, byte[]> classes;
-        private final Map<String, Class<?>> cache = new HashMap<>();
-
-        MemClassLoader(Map<String, byte[]> classes) {
-            super(null);
-            this.classes = classes;
-        }
-
-        @Override
-        public Class findClass(String name) throws ClassNotFoundException {
-            Class<?> clazz = cache.get(name);
-            if (clazz == null) {
-                byte[] b = classes.get(name);
-                if (b == null) {
-                    return super.findClass(name);
-                } else {
-                    clazz = defineClass(name, b, 0, b.length);
-                    cache.put(name, clazz);
-                }
-            }
-            return clazz;
-        }
-    }
-
-    public static void main(String[] args) throws Exception {
-        helper = Helper.newHelper();
-        if (helper == null) {
-            System.err.println("Test not run");
-            return;
-        }
-
-        testForName();
-
-        helper.generateDefaultModules();
-        helper.generateDefaultJModule("optim1", "java.se");
-        {
-            String[] userOptions = {"--class-optim=all:log=./class-optim-log.txt"};
-
-            Path imageDir = helper.generateDefaultImage(userOptions, "optim1").assertSuccess();
-            helper.checkImage(imageDir, "optim1", null, null);
-        }
-
-        {
-            String[] userOptions = {"--class-optim=forName-folding:log=./class-optim-log.txt"};
-            Path imageDir = helper.generateDefaultImage(userOptions, "optim1").assertSuccess();
-            helper.checkImage(imageDir, "optim1", null, null);
-        }
-
-        {
-            ControlFlowPlugin plugin = new ControlFlowPlugin();
-            PluginRepository.registerPlugin(plugin);
-            String[] userOptions = {"--test-optim"};
-            Path imageDir = helper.generateDefaultImage(userOptions, "optim1").assertSuccess();
-            helper.checkImage(imageDir, "optim1", null, null);
-            //System.out.println("Num methods analyzed " + provider.numMethods
-            //        + "num blocks " + provider.numBlocks);
-            if (!plugin.called) {
-                throw new Exception("Plugin not called");
-            }
-            if (plugin.numMethods < 1000) {
-                throw new Exception("Not enough method called,  should be "
-                        + "around 10000 but is " + plugin.numMethods);
-            }
-            if (plugin.numBlocks < 100000) {
-                throw new Exception("Not enough blocks,  should be "
-                        + "around 640000 but is " + plugin.numMethods);
-            }
-        }
-    }
-
-}
--- a/test/tools/jlink/asmplugin/AddForgetResourcesTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,509 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test resource transformation.
- * @author Andrei Eremeev
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- *          jdk.jdeps/com.sun.tools.classfile
- * @build AsmPluginTestBase
- * @run main AddForgetResourcesTest
-*/
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-
-import com.sun.tools.classfile.ClassFile;
-import com.sun.tools.classfile.Method;
-import java.io.UncheckedIOException;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class AddForgetResourcesTest extends AsmPluginTestBase {
-
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new AddForgetResourcesTest().test();
-    }
-
-    @Override
-    public void test() throws Exception {
-        TestPlugin[] plugins = new TestPlugin[] {
-                new AddClassesPlugin(),
-                new AddResourcesPlugin(),
-                new ReplaceClassesPlugin(),
-                new ReplaceResourcesPlugin(),
-                new ForgetClassesPlugin(),
-                new ForgetResourcesPlugin(),
-                new AddForgetClassesPlugin(),
-                new AddForgetResourcesPlugin(),
-                new ComboPlugin()
-        };
-        for (TestPlugin p : plugins) {
-            ModulePool out = p.visit(getPool());
-            p.test(getPool(), out);
-        }
-    }
-
-    private static final String SUFFIX = "HELLOWORLD";
-
-    private static class RenameClassVisitor extends ClassVisitor {
-
-        public RenameClassVisitor(ClassWriter cv) {
-            super(Opcodes.ASM5, cv);
-        }
-
-        @Override
-        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-            super.visit(version, access, name + SUFFIX, signature, superName, interfaces);
-        }
-    }
-
-    private static class AddMethodClassVisitor extends ClassVisitor {
-
-        public AddMethodClassVisitor(ClassWriter cv) {
-            super(Opcodes.ASM5, cv);
-        }
-
-        @Override
-        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-            this.visitMethod(0, SUFFIX, "()V", null, null);
-            super.visit(version, access, name, signature, superName, interfaces);
-        }
-    }
-
-    private class AddClassesPlugin extends TestPlugin {
-
-        private int expected = 0;
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            expected = globalPool.getClasses().size();
-            for (ModuleEntry res : globalPool.getClasses()) {
-                ClassReader reader = globalPool.getClassReader(res);
-                String className = reader.getClassName();
-                if (!className.endsWith("module-info")) {
-                    ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                    reader.accept(new RenameClassVisitor(writer), ClassReader.EXPAND_FRAMES);
-                    transformedClasses.addClass(writer);
-                    ++expected;
-                }
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) {
-            Collection<ModuleEntry> inClasses = extractClasses(inResources);
-            Collection<ModuleEntry> outClasses = extractClasses(outResources);
-            if (expected != outClasses.size()) {
-                throw new AssertionError("Classes were not added. Expected: " + expected
-                        + ", got: " + outClasses.size());
-            }
-            for (ModuleEntry in : inClasses) {
-                String path = in.getPath();
-                if (!outClasses.contains(in)) {
-                    throw new AssertionError("Class not found: " + path);
-                }
-                if (path.endsWith("module-info.class")) {
-                    continue;
-                }
-                String modifiedPath = path.replace(".class", SUFFIX + ".class");
-                if (!outClasses.contains(ModuleEntry.create(modifiedPath, new byte[0]))) {
-                    throw new AssertionError("Class not found: " + modifiedPath);
-                }
-            }
-        }
-    }
-
-    private class AddResourcesPlugin extends TestPlugin {
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            for (ModuleEntry res : globalPool.getResourceFiles()) {
-                String path = res.getPath();
-                String moduleName = getModule(path);
-                AsmModulePool modulePool = pools.getModulePool(moduleName);
-                WritableResourcePool resourcePool = modulePool.getTransformedResourceFiles();
-                resourcePool.addResourceFile(new ResourceFile(removeModule(res.getPath()) + SUFFIX,
-                        res.getBytes()));
-            }
-        }
-
-        @Override
-        public void test(ModulePool in, ModulePool out) throws Exception {
-            Collection<ModuleEntry> inResources = extractResources(in);
-            Collection<ModuleEntry> outResources = extractResources(out);
-            if (2 * inResources.size() != outResources.size()) {
-                throw new AssertionError("Classes were not added. Expected: " + (2 * inResources.size())
-                        + ", got: " + outResources.size());
-            }
-            for (ModuleEntry r : inResources) {
-                String path = r.getPath();
-                if (!outResources.contains(r)) {
-                    throw new AssertionError("Class not found: " + path);
-                }
-                String modifiedPath = path + SUFFIX;
-                if (!outResources.contains(ModuleEntry.create(modifiedPath, new byte[0]))) {
-                    throw new AssertionError("Class not found: " + modifiedPath);
-                }
-            }
-        }
-    }
-
-    private class ReplaceClassesPlugin extends TestPlugin {
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            for (ModuleEntry res : globalPool.getClasses()) {
-                ClassReader reader = globalPool.getClassReader(res);
-                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                reader.accept(new AddMethodClassVisitor(writer), ClassReader.EXPAND_FRAMES);
-                transformedClasses.addClass(writer);
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            Collection<ModuleEntry> inClasses = extractClasses(inResources);
-            Collection<ModuleEntry> outClasses = extractClasses(outResources);
-            if (inClasses.size() != outClasses.size()) {
-                throw new AssertionError("Number of classes. Expected: " + (inClasses.size())
-                        + ", got: " + outClasses.size());
-            }
-            for (ModuleEntry out : outClasses) {
-                String path = out.getPath();
-                if (!inClasses.contains(out)) {
-                    throw new AssertionError("Class not found: " + path);
-                }
-                ClassFile cf = ClassFile.read(new ByteArrayInputStream(out.getBytes()));
-                if (path.endsWith("module-info.class")) {
-                    continue;
-                }
-                boolean failed = true;
-                for (Method m : cf.methods) {
-                    if (m.getName(cf.constant_pool).equals(SUFFIX)) {
-                        failed = false;
-                    }
-                }
-                if (failed) {
-                    throw new AssertionError("Not found method with name " + SUFFIX + " in class " + path);
-                }
-            }
-        }
-    }
-
-    private class ReplaceResourcesPlugin extends TestPlugin {
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            for (ModuleEntry res : globalPool.getResourceFiles()) {
-                String path = res.getPath();
-                AsmModulePool modulePool = pools.getModulePool(getModule(path));
-                modulePool.getTransformedResourceFiles().addResourceFile(new ResourceFile(removeModule(path),
-                        "HUI".getBytes()));
-            }
-        }
-
-        @Override
-        public void test(ModulePool in, ModulePool out) throws Exception {
-            Collection<ModuleEntry> inResources = extractResources(in);
-            Collection<ModuleEntry> outResources = extractResources(out);
-            if (inResources.size() != outResources.size()) {
-                throw new AssertionError("Number of resources. Expected: " + inResources.size()
-                        + ", got: " + outResources.size());
-            }
-            for (ModuleEntry r : outResources) {
-                String path = r.getPath();
-                if (!inResources.contains(r)) {
-                    throw new AssertionError("Resource not found: " + path);
-                }
-                String content = new String(r.getBytes());
-                if (!"HUI".equals(content)) {
-                    throw new AssertionError("Content expected: 'HUI', got: " + content);
-                }
-            }
-        }
-    }
-
-    private class ForgetClassesPlugin extends TestPlugin {
-
-        private int expected = 0;
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            int i = 0;
-            for (ModuleEntry res : globalPool.getClasses()) {
-                String path = removeModule(res.getPath());
-                String className = path.replace(".class", "");
-                if ((i & 1) == 0 && !className.endsWith("module-info")) {
-                    transformedClasses.forgetClass(className);
-                } else {
-                    ++expected;
-                }
-                i ^= 1;
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            Collection<ModuleEntry> outClasses = extractClasses(outResources);
-            if (expected != outClasses.size()) {
-                throw new AssertionError("Number of classes. Expected: " + expected +
-                        ", got: " + outClasses.size());
-            }
-        }
-    }
-
-    private class ForgetResourcesPlugin extends TestPlugin {
-
-        private int expectedAmount = 0;
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            int i = 0;
-            for (ModuleEntry res : globalPool.getResourceFiles()) {
-                String path = res.getPath();
-                if (!path.contains("META-INF/services")) {
-                    if ((i & 1) == 0) {
-                        AsmModulePool modulePool = pools.getModulePool(getModule(path));
-                        modulePool.getTransformedResourceFiles().forgetResourceFile(removeModule(res.getPath()));
-                    } else {
-                        ++expectedAmount;
-                    }
-                    i ^= 1;
-                } else {
-                    ++expectedAmount;
-                }
-            }
-        }
-
-        @Override
-        public void test(ModulePool in, ModulePool out) throws Exception {
-            Collection<ModuleEntry> outResources = extractResources(out);
-            if (expectedAmount != outResources.size()) {
-                throw new AssertionError("Number of classes. Expected: " + expectedAmount
-                        + ", got: " + outResources.size());
-            }
-        }
-    }
-
-    private class AddForgetClassesPlugin extends TestPlugin {
-
-        private int expected = 0;
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            int i = 0;
-            for (ModuleEntry res : globalPool.getClasses()) {
-                ClassReader reader = globalPool.getClassReader(res);
-                String className = reader.getClassName();
-                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                if (!className.endsWith("module-info")) {
-                    reader.accept(new RenameClassVisitor(writer), ClassReader.EXPAND_FRAMES);
-                    transformedClasses.addClass(writer);
-                    ++expected;
-                }
-
-                if ((i & 1) == 0 && !className.endsWith("module-info")) {
-                    transformedClasses.forgetClass(className);
-                } else {
-                    ++expected;
-                }
-                i ^= 1;
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            Collection<ModuleEntry> outClasses = extractClasses(outResources);
-            if (expected != outClasses.size()) {
-                throw new AssertionError("Number of classes. Expected: " + expected
-                        + ", got: " + outClasses.size());
-            }
-        }
-    }
-
-    private class AddForgetResourcesPlugin extends TestPlugin {
-
-        private int expectedAmount = 0;
-
-        @Override
-        public void visit() {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            int i = 0;
-            for (ModuleEntry res : globalPool.getResourceFiles()) {
-                String path = res.getPath();
-                String moduleName = getModule(path);
-                if (!path.contains("META-INF")) {
-                    AsmModulePool modulePool = pools.getModulePool(moduleName);
-                    WritableResourcePool transformedResourceFiles = modulePool.getTransformedResourceFiles();
-                    String newPath = removeModule(path) + SUFFIX;
-                    transformedResourceFiles.addResourceFile(new ResourceFile(newPath, res.getBytes()));
-                    if ((i & 1) == 0) {
-                        transformedResourceFiles.forgetResourceFile(newPath);
-                    } else {
-                        ++expectedAmount;
-                    }
-                    i ^= 1;
-                }
-                ++expectedAmount;
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool out) throws Exception {
-            Collection<ModuleEntry> outResources = extractResources(out);
-            if (expectedAmount != outResources.size()) {
-                throw new AssertionError("Number of classes. Expected: " + expectedAmount
-                        + ", got: " + outResources.size());
-            }
-        }
-    }
-
-    private class ComboPlugin extends TestPlugin {
-
-        private class RenameClassVisitor extends ClassVisitor {
-
-            public RenameClassVisitor(ClassWriter cv) {
-                super(Opcodes.ASM5, cv);
-            }
-
-            @Override
-            public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-                super.visit(version, access, name + SUFFIX, signature, superName, interfaces);
-            }
-        }
-
-        @Override
-        public void visit() {
-            try {
-                renameClasses();
-                renameResources();
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            if (!isVisitCalled()) {
-                throw new AssertionError("Resources not visited");
-            }
-            AsmGlobalPool globalPool = getPools().getGlobalPool();
-            if (globalPool.getTransformedClasses().getClasses().size() != getClasses().size()) {
-                throw new AssertionError("Number of transformed classes not equal to expected");
-            }
-            // Check that only renamed classes and resource files are in the result.
-            outResources.entries().forEach(r -> {
-                String resourceName = r.getPath();
-                if (resourceName.endsWith(".class") && !resourceName.endsWith("module-info.class")) {
-                    if (!resourceName.endsWith(SUFFIX + ".class")) {
-                        throw new AssertionError("Class not renamed " + resourceName);
-                    }
-                } else if (resourceName.contains("META-INF/services/") && MODULES.containsKey(r.getModule())) {
-                    String newClassName = new String(r.getBytes());
-                    if(!newClassName.endsWith(SUFFIX)) {
-                        throw new AssertionError("Resource file not renamed " + resourceName);
-                    }
-                }
-            });
-        }
-
-        private void renameResources() throws IOException {
-            AsmPools pools = getPools();
-            // Rename the resource Files
-            for (Map.Entry<String, List<String>> mod : MODULES.entrySet()) {
-                String moduleName = mod.getKey();
-                AsmModulePool modulePool = pools.getModulePool(moduleName);
-                for (ModuleEntry res : modulePool.getResourceFiles()) {
-                    ResourceFile resFile = modulePool.getResourceFile(res);
-                    if (resFile.getPath().startsWith("META-INF/services/")) {
-                        String newContent = new String(resFile.getContent()) + SUFFIX;
-                        ResourceFile newResourceFile = new ResourceFile(resFile.getPath(),
-                                newContent.getBytes());
-                        modulePool.getTransformedResourceFiles().addResourceFile(newResourceFile);
-                    }
-                }
-            }
-        }
-
-        private void renameClasses() throws IOException {
-            AsmPools pools = getPools();
-            AsmGlobalPool globalPool = pools.getGlobalPool();
-            WritableClassPool transformedClasses = globalPool.getTransformedClasses();
-            for (ModuleEntry res : globalPool.getClasses()) {
-                if (res.getPath().endsWith("module-info.class")) {
-                    continue;
-                }
-                ClassReader reader = globalPool.getClassReader(res);
-                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                RenameClassVisitor visitor = new RenameClassVisitor(writer);
-                reader.accept(visitor, ClassReader.EXPAND_FRAMES);
-
-                transformedClasses.forgetClass(reader.getClassName());
-                transformedClasses.addClass(writer);
-            }
-        }
-    }
-}
--- a/test/tools/jlink/asmplugin/AsmPluginTestBase.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-import java.io.IOException;
-import java.net.URI;
-import java.nio.file.FileSystem;
-import java.nio.file.FileSystems;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.function.Predicate;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.internal.StringTable;
-
-import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public abstract class AsmPluginTestBase {
-
-    protected static final String TEST_MODULE = "jlink.test";
-    protected static final Map<String, List<String>> MODULES;
-
-    private static final Predicate<ModuleEntry> isClass = r -> r.getPath().endsWith(".class");
-    private final List<String> classes;
-    private final List<String> resources;
-    private final ModulePool pool;
-
-    static {
-        Map<String, List<String>> map = new HashMap<>();
-        map.put("jdk.localedata", new ArrayList<>());
-        map.put("java.base", new ArrayList<>());
-        map.put(TEST_MODULE, new ArrayList<>());
-        MODULES = Collections.unmodifiableMap(map);
-    }
-
-    public static boolean isImageBuild() {
-        Path javaHome = Paths.get(System.getProperty("test.jdk"));
-        Path jmods = javaHome.resolve("jmods");
-        return Files.exists(jmods);
-    }
-
-    public AsmPluginTestBase() {
-        try {
-            List<String> classes = new ArrayList<>();
-            List<String> resources = new ArrayList<>();
-
-            pool = new ModulePoolImpl();
-
-            FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
-            Path root = fs.getPath("/modules");
-
-            List<byte[]> moduleInfos = new ArrayList<>();
-            try (Stream<Path> stream = Files.walk(root)) {
-                for (Iterator<Path> iterator = stream.iterator(); iterator.hasNext(); ) {
-                    Path p = iterator.next();
-                    if (Files.isRegularFile(p)) {
-                        String module = p.toString().substring("/modules/".length());
-                        module = module.substring(0, module.indexOf("/"));
-                        if (MODULES.keySet().contains(module)) {
-                            try {
-                                boolean isModuleInfo = p.endsWith("module-info.class");
-                                if (isModuleInfo) {
-                                    moduleInfos.add(Files.readAllBytes(p));
-                                }
-                                byte[] content = Files.readAllBytes(p);
-                                if (p.toString().endsWith(".class") && !isModuleInfo) {
-                                    classes.add(toClassName(p));
-                                } else if (!isModuleInfo) {
-                                    MODULES.get(module).add(toResourceFile(p));
-                                }
-                                resources.add(toPath(p.toString()));
-                                ModuleEntry res = ModuleEntry.create(toPath(p.toString()), content);
-                                pool.add(res);
-                            } catch (Exception ex) {
-                                throw new RuntimeException(ex);
-                            }
-                        }
-                    }
-                }
-            }
-            // There is more than 10 classes in java.base...
-            if (classes.size() < 10 || pool.getEntryCount() < 10) {
-                throw new AssertionError("Not expected resource or class number");
-            }
-
-            //Add a fake resource file
-            String content = "java.lang.Object";
-            String path = "META-INF/services/com.foo.BarProvider";
-            ModuleEntry resFile = ModuleEntry.create("/" + TEST_MODULE + "/" +
-                    path, content.getBytes());
-            pool.add(resFile);
-            ModuleEntry fakeInfoFile = ModuleEntry.create("/" + TEST_MODULE
-                    + "/module-info.class", moduleInfos.get(0));
-            pool.add(fakeInfoFile);
-            MODULES.get(TEST_MODULE).add(path);
-            for(Map.Entry<String, List<String>> entry : MODULES.entrySet()) {
-                if (entry.getValue().isEmpty()) {
-                    throw new AssertionError("No resource file for " + entry.getKey());
-                }
-            }
-            this.classes = Collections.unmodifiableList(classes);
-            this.resources = Collections.unmodifiableList(resources);
-        } catch (Exception e) {
-            throw new ExceptionInInitializerError(e);
-        }
-    }
-
-    public List<String> getClasses() {
-        return classes;
-    }
-
-    public List<String> getResources() {
-        return resources;
-    }
-
-    public ModulePool getPool() {
-        return pool;
-    }
-
-    public abstract void test() throws Exception;
-
-    public Collection<ModuleEntry> extractClasses(ModulePool pool) {
-        return pool.entries()
-                .filter(isClass)
-                .collect(Collectors.toSet());
-    }
-
-    public Collection<ModuleEntry> extractResources(ModulePool pool) {
-        return pool.entries()
-                .filter(isClass.negate())
-                .collect(Collectors.toSet());
-    }
-
-    public String getModule(String path) {
-        int index = path.indexOf("/", 1);
-        return path.substring(1, index);
-    }
-
-    public String removeModule(String path) {
-        int index = path.indexOf("/", 1);
-        return path.substring(index + 1);
-    }
-
-    private String toPath(String p) {
-        return p.substring("/modules".length());
-    }
-
-    private String toClassName(Path p) {
-        String path = p.toString();
-        path = path.substring("/modules/".length());
-        // remove module
-        if (!path.endsWith("module-info.class")) {
-            path = path.substring(path.indexOf("/") + 1);
-        }
-        path = path.substring(0, path.length() - ".class".length());
-
-        return path;
-    }
-
-    private String toResourceFile(Path p) {
-        String path = p.toString();
-        path = path.substring("/modules/".length());
-        // remove module
-        path = path.substring(path.indexOf("/") + 1);
-
-        return path;
-    }
-
-    public abstract class TestPlugin extends AsmPlugin {
-
-        private AsmPools pools;
-
-        public AsmPools getPools() {
-            return pools;
-        }
-
-        public boolean isVisitCalled() {
-            return pools != null;
-        }
-
-        public ModulePool visit(ModulePool inResources) throws IOException {
-            try {
-                ModulePool outResources = new ModulePoolImpl(inResources.getByteOrder(), new StringTable() {
-                    @Override
-                    public int addString(String str) {
-                        return -1;
-                    }
-
-                    @Override
-                    public String getString(int id) {
-                        return null;
-                    }
-                });
-                visit(inResources, outResources);
-                return outResources;
-            } catch (Exception e) {
-                throw new IOException(e);
-            }
-        }
-
-        @Override
-        public void visit(AsmPools pools) {
-            if (isVisitCalled()) {
-                throw new AssertionError("Visit was called twice");
-            }
-            this.pools = pools;
-            visit();
-        }
-
-        public abstract void visit();
-        public abstract void test(ModulePool inResources, ModulePool outResources) throws Exception;
-
-        @Override
-        public String getName() {
-            return "test-plugin";
-        }
-    }
-}
--- a/test/tools/jlink/asmplugin/BasicTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,177 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test basic functionality.
- * @author Jean-Francois Denise
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- * @build AsmPluginTestBase
- * @run main BasicTest
- */
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class BasicTest extends AsmPluginTestBase {
-
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new BasicTest().test();
-    }
-
-    @Override
-    public void test() throws Exception {
-        BasicPlugin basicPlugin = new BasicPlugin(getClasses());
-        ModulePool res = basicPlugin.visit(getPool());
-        basicPlugin.test(getPool(), res);
-    }
-
-    private class BasicPlugin extends TestPlugin {
-
-        private final List<String> classes;
-
-        public BasicPlugin(List<String> classes) {
-            this.classes = classes;
-        }
-
-        @Override
-        public void visit() {
-            for (String m : MODULES.keySet()) {
-                AsmModulePool pool = getPools().getModulePool(m);
-                if (pool == null) {
-                    throw new AssertionError(m + " pool not found");
-                }
-                if(!pool.getModuleName().equals(m)) {
-                    throw new AssertionError("Invalid module name " +
-                            pool.getModuleName() + " should be "+ m);
-                }
-                if (pool.getClasses().size() == 0 && !m.equals(TEST_MODULE)) {
-                    throw new AssertionError("Empty pool " + m);
-                }
-                pool.addPackage("toto");
-                if (!pool.getTransformedClasses().getClasses().isEmpty()) {
-                    throw new AssertionError("Should be empty");
-                }
-                for(String res : MODULES.get(m)) {
-                    AsmPool.ResourceFile resFile = pool.getResourceFile(res);
-                    if(resFile == null) {
-                        throw new AssertionError("No resource file for " + res);
-                    }
-                }
-            }
-            try {
-                testPools();
-                testVisitor();
-            } catch (IOException ex) {
-                throw new UncheckedIOException(ex);
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            if (!isVisitCalled()) {
-                throw new AssertionError("Resources not visited");
-            }
-            if (inResources.getEntryCount() != outResources.getEntryCount()) {
-                throw new AssertionError("Input size " + inResources.getEntryCount() +
-                        " != to " + outResources.getEntryCount());
-            }
-        }
-
-        private void testVisitor() throws IOException {
-            List<String> seen = new ArrayList<>();
-            getPools().getGlobalPool().visitClassReaders((reader) -> {
-                String className = reader.getClassName();
-                // Wrong naming of module-info.class in ASM
-                if (className.endsWith("module-info")) {
-                    return null;
-                }
-                if (!classes.contains(className)) {
-                    throw new AssertionError("Class is not expected " + className);
-                }
-                if (getPools().getGlobalPool().getClassReader(className) == null) {
-                    throw new AssertionError("Class not found in pool " + className);
-                }
-                seen.add(className);
-                return null;
-            });
-
-            if (!seen.equals(classes)) {
-                throw new AssertionError("Expected and seen are not equal");
-            }
-        }
-
-        private void testPools() throws IOException {
-            Set<String> remain = new HashSet<>(classes);
-            for (ModuleEntry res : getPools().getGlobalPool().getClasses()) {
-                ClassReader reader = getPools().getGlobalPool().getClassReader(res);
-                String className = reader.getClassName();
-                // Wrong naming of module-info.class in ASM
-                if (className.endsWith("module-info")) {
-                    continue;
-                }
-                if (!classes.contains(className)) {
-                    throw new AssertionError("Class is not expected " + className);
-                }
-                if (getPools().getGlobalPool().getClassReader(className) == null) {
-                    throw new AssertionError("Class " + className + " not found in pool ");
-                }
-                // Check the module pool
-                boolean found = false;
-                for(AsmModulePool mp : getPools().getModulePools()) {
-                    if(mp.getClassReader(className) != null) {
-                        found = true;
-                        break;
-                    }
-                }
-                if(!found) {
-                    throw new AssertionError("No modular pool for " +
-                            className);
-                }
-                remain.remove(className);
-            }
-            if (!remain.isEmpty()) {
-                throw new AssertionError("Remaining classes " + remain);
-            }
-        }
-    }
-}
--- a/test/tools/jlink/asmplugin/IdentityPluginTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test basic functionality.
- * @author Jean-Francois Denise
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- * @build AsmPluginTestBase
- * @run main IdentityPluginTest
- */
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.UncheckedIOException;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableClassPool;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class IdentityPluginTest extends AsmPluginTestBase {
-
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new IdentityPluginTest().test();
-    }
-
-    public void test() throws Exception {
-        IdentityPlugin asm = new IdentityPlugin();
-        ModulePool resourcePool = asm.visit(getPool());
-        asm.test(getPool(), resourcePool);
-    }
-
-    private class IdentityPlugin extends TestPlugin {
-
-        @Override
-        public void visit() {
-            for (ModuleEntry res : getPools().getGlobalPool().getClasses()) {
-                if (res.getPath().endsWith("module-info.class")) {
-                    continue;
-                }
-                ClassReader reader = getPools().getGlobalPool().getClassReader(res);
-                ClassWriter writer = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                IdentityClassVisitor visitor = new IdentityClassVisitor(writer);
-                reader.accept(visitor, ClassReader.EXPAND_FRAMES);
-                getPools().getGlobalPool().getTransformedClasses().addClass(writer);
-            }
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws IOException {
-            if (outResources.isEmpty()) {
-                throw new AssertionError("Empty result");
-            }
-            if (!isVisitCalled()) {
-                throw new AssertionError("Resources not visited");
-            }
-            WritableClassPool transformedClasses = getPools().getGlobalPool().getTransformedClasses();
-            if (transformedClasses.getClasses().size() != getClasses().size()) {
-                throw new AssertionError("Number of transformed classes not equal to expected");
-            }
-            for (String className : getClasses()) {
-                if (transformedClasses.getClassReader(className) == null) {
-                    throw new AssertionError("Class not transformed " + className);
-                }
-            }
-            outResources.entries().forEach(r -> {
-                if (r.getPath().endsWith(".class") && !r.getPath().endsWith("module-info.class")) {
-                    try {
-                        ClassReader reader = new ClassReader(new ByteArrayInputStream(r.getBytes()));
-                        ClassWriter w = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                        reader.accept(w, ClassReader.EXPAND_FRAMES);
-                    } catch (IOException exp) {
-                        throw new UncheckedIOException(exp);
-                    }
-                }
-            });
-        }
-
-        @Override
-        public String getName() {
-            return "identity-plugin";
-        }
-    }
-
-    private static class IdentityClassVisitor extends ClassVisitor {
-        public IdentityClassVisitor(ClassWriter cv) {
-            super(Opcodes.ASM5, cv);
-        }
-    }
-}
--- a/test/tools/jlink/asmplugin/NegativeTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,172 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test basic functionality.
- * @author Andrei Eremeev
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- * @build AsmPluginTestBase
- * @run main NegativeTest
- */
-
-import java.io.IOException;
-import java.io.UncheckedIOException;
-import java.nio.ByteOrder;
-import java.util.Map;
-import java.util.Set;
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.tools.jlink.plugin.Plugin;
-import jdk.tools.jlink.internal.ModulePoolImpl;
-import jdk.tools.jlink.internal.StringTable;
-import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPlugin;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class NegativeTest extends AsmPluginTestBase {
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new NegativeTest().test();
-    }
-
-    @Override
-    public void test() throws Exception {
-        testNull();
-        testUnknownPackage();
-    }
-
-    private void testUnknownPackage() throws Exception {
-        AsmPlugin t = new AsmPlugin() {
-            @Override
-            public void visit(AsmPools pools) {
-                try {
-                    AsmGlobalPool globalPool = pools.getGlobalPool();
-                    AsmModulePool javabase = pools.getModulePool("java.base");
-                    ClassReader cr = new ClassReader(NegativeTest.class.getResourceAsStream("NegativeTest.class"));
-                    ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES);
-                    cr.accept(new RenameClassVisitor(cw), ClassReader.EXPAND_FRAMES);
-                    action(() -> globalPool.getTransformedClasses().addClass(cw),
-                            "Unknown package", PluginException.class);
-                    action(() -> javabase.getTransformedClasses().addClass(cw),
-                            "Unknown package", PluginException.class);
-
-                    ResourceFile newResFile = new ResourceFile("java/aaa/file", new byte[0]);
-                    action(() -> globalPool.getTransformedResourceFiles().addResourceFile(newResFile),
-                            "Unknown package", PluginException.class);
-                    action(() -> javabase.getTransformedResourceFiles().addResourceFile(newResFile),
-                            "Unknown package", PluginException.class);
-
-                    action(() -> globalPool.getTransformedClasses().forgetClass("java/aaa/file"),
-                            "Unknown package", PluginException.class);
-                    action(() -> javabase.getTransformedClasses().forgetClass("java/aaa/file"),
-                            "Unknown package", PluginException.class);
-                    action(() -> globalPool.getTransformedResourceFiles().forgetResourceFile("java/aaa/file"),
-                            "Unknown package", PluginException.class);
-                    action(() -> javabase.getTransformedResourceFiles().forgetResourceFile("java/aaa/file"),
-                            "Unknown package", PluginException.class);
-                } catch (IOException ex) {
-                   throw new UncheckedIOException(ex);
-                }
-            }
-        };
-        ModulePool resources = new ModulePoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
-            @Override
-            public int addString(String str) {
-                return -1;
-            }
-
-            @Override
-            public String getString(int id) {
-                throw new UnsupportedOperationException("Not supported yet.");
-            }
-        });
-        t.visit(getPool(), resources);
-    }
-
-    private static class RenameClassVisitor extends ClassVisitor {
-
-        public RenameClassVisitor(ClassWriter cv) {
-            super(Opcodes.ASM5, cv);
-        }
-
-        @Override
-        public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
-            super.visit(version, access, "RENAMED", signature, superName, interfaces);
-        }
-    }
-
-    private void testNull() throws Exception {
-        AsmPlugin t = new AsmPlugin() {
-            @Override
-            public void visit(AsmPools pools) {
-                action(() -> pools.getModulePool(null), "Module name is null", NullPointerException.class);
-                action(() -> pools.fillOutputResources(null), "Output resource is null", NullPointerException.class);
-            }
-        };
-        ModulePool resources = new ModulePoolImpl(ByteOrder.BIG_ENDIAN, new StringTable() {
-            @Override
-            public int addString(String str) {
-                return -1;
-            }
-
-            @Override
-            public String getString(int id) {
-                throw new UnsupportedOperationException("Not supported yet.");
-            }
-        });
-        action(() -> t.visit(null, resources), "Input resource is null", NullPointerException.class);
-        action(() -> t.visit(resources, null), "Output resource is null", NullPointerException.class);
-        t.visit(resources, resources);
-    }
-
-    private void action(Action action, String message, Class<? extends Exception> expected) {
-        try {
-            System.err.println("Testing: " + message);
-            action.call();
-            throw new AssertionError(message + ": should have failed");
-        } catch (Exception e) {
-            if (!expected.isInstance(e)) {
-                throw new RuntimeException(e);
-            } else {
-                System.err.println("Got exception as expected: " + e);
-            }
-        }
-    }
-
-    private interface Action {
-        void call() throws Exception;
-    }
-}
--- a/test/tools/jlink/asmplugin/PackageMappingTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test plugins
- * @author Andrei Eremeev
- * @modules jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- * @run main PackageMappingTest
- */
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import jdk.tools.jlink.internal.plugins.asm.AsmGlobalPool;
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.WritableResourcePool;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class PackageMappingTest extends AsmPluginTestBase {
-
-    private final List<String> newFiles = Arrays.asList(
-            "/java.base/a1/bbb/c",
-            "/" + TEST_MODULE + "/a2/bbb/d"
-    );
-
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new PackageMappingTest().test();
-    }
-
-    public void test() throws Exception {
-        TestPlugin[] plugins = new TestPlugin[]{
-            new PackageMappingPlugin(newFiles, false),
-            new PackageMappingPlugin(newFiles, true)
-        };
-        for (TestPlugin p : plugins) {
-            ModulePool pool = p.visit(getPool());
-            p.test(getPool(), pool);
-        }
-    }
-
-    public class PackageMappingPlugin extends TestPlugin {
-
-        private final Map<String, List<ResourceFile>> newFiles;
-        private final boolean testGlobal;
-
-        private String getModuleName(String res) {
-            return res.substring(1, res.indexOf("/", 1));
-        }
-
-        private PackageMappingPlugin(List<String> files, boolean testGlobal) {
-            this.newFiles = new HashMap<>();
-            this.testGlobal = testGlobal;
-            for (String file : files) {
-                String moduleName = getModuleName(file);
-                String path = file.substring(1 + moduleName.length() + 1);
-                newFiles.computeIfAbsent(moduleName, $ -> new ArrayList<>()).add(
-                        new ResourceFile(path, new byte[0]));
-            }
-        }
-
-        @Override
-        public void visit() {
-            testMapToUnknownModule();
-            testMapPackageTwice();
-            testPackageMapping();
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) {
-            Set<String> in = getPools().getGlobalPool().getResourceFiles().stream()
-                    .map(ModuleEntry::getPath)
-                    .collect(Collectors.toSet());
-            Set<String> out = extractResources(outResources).stream()
-                    .map(ModuleEntry::getPath)
-                    .collect(Collectors.toSet());
-            in.addAll(PackageMappingTest.this.newFiles);
-            if (!Objects.equals(in, out)) {
-                throw new AssertionError("Expected: " + in + ", got: " + outResources);
-            }
-        }
-
-        private void testPackageMapping() {
-            AsmGlobalPool globalPool = getPools().getGlobalPool();
-            try {
-                Map<String, Set<String>> mappedPackages = new HashMap<>();
-                Function<String, Set<String>> produceSet = $ -> new HashSet<>();
-                for (Map.Entry<String, List<ResourceFile>> entry : newFiles.entrySet()) {
-                    String moduleName = entry.getKey();
-                    Set<String> module = mappedPackages.computeIfAbsent(moduleName, produceSet);
-                    AsmModulePool modulePool = getPools().getModulePool(moduleName);
-                    for (ResourceFile r : entry.getValue()) {
-                        String name = r.getPath();
-                        String packageName = name.substring(0, name.lastIndexOf('/'));
-                        if (module.add(packageName)) {
-                            globalPool.addPackageModuleMapping(packageName, moduleName);
-                        }
-                        WritableResourcePool transformedResourceFiles = testGlobal
-                                ? globalPool.getTransformedResourceFiles()
-                                : modulePool.getTransformedResourceFiles();
-                        transformedResourceFiles.addResourceFile(r);
-                    }
-                    try {
-                        modulePool.getTransformedResourceFiles().addResourceFile(
-                                new ResourceFile("a3/bbb", new byte[0]));
-                        throw new AssertionError("Exception expected");
-                    } catch (Exception ex) {
-                        // expected
-                    }
-                }
-                try {
-                    globalPool.getTransformedResourceFiles().addResourceFile(
-                            new ResourceFile("a3/bbb", new byte[0]));
-                    throw new AssertionError("Exception expected");
-                } catch (Exception ex) {
-                    // expected
-                }
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        }
-
-        private void testMapPackageTwice() {
-            try {
-                AsmGlobalPool globalPool = getPools().getGlobalPool();
-                globalPool.addPackageModuleMapping("a/p1", TEST_MODULE);
-                globalPool.addPackageModuleMapping("a/p1", TEST_MODULE);
-                throw new AssertionError("Exception expected after mapping a package twice to the same module");
-            } catch (Exception e) {
-                if (e instanceof PluginException) {
-                    // expected
-                    String message = e.getMessage();
-                    if (!(TEST_MODULE + " module already contains package a.p1").equals(message)) {
-                        throw new AssertionError(e);
-                    }
-                } else {
-                    throw new AssertionError(e);
-                }
-            }
-        }
-
-        private void testMapToUnknownModule() {
-            AsmModulePool unknownModule = getPools().getModulePool("UNKNOWN");
-            if (unknownModule != null) {
-                throw new AssertionError("getModulePool returned not null value: " + unknownModule.getModuleName());
-            }
-            try {
-                AsmGlobalPool globalPool = getPools().getGlobalPool();
-                globalPool.addPackageModuleMapping("a/b", "UNKNOWN");
-                throw new AssertionError("Exception expected after mapping a package to unknown module");
-            } catch (Exception e) {
-                String message = e.getMessage();
-                if (message == null || !message.startsWith("Unknown module UNKNOWN")) {
-                    throw new AssertionError(e);
-                }
-            }
-        }
-    }
-}
--- a/test/tools/jlink/asmplugin/SortingTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,183 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test resource sorting.
- * @author Jean-Francois Denise
- * @modules jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- * @build AsmPluginTestBase
- * @run main SortingTest
- */
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-import java.util.stream.Collectors;
-
-import jdk.tools.jlink.internal.plugins.asm.AsmModulePool;
-import jdk.tools.jlink.plugin.PluginException;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class SortingTest extends AsmPluginTestBase {
-
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new SortingTest().test();
-    }
-
-    @Override
-    public void test() {
-        try {
-            classSorting();
-            moduleSorting();
-        } catch (Exception ex) {
-            throw new PluginException(ex);
-        }
-    }
-
-    private void classSorting() throws Exception {
-        List<String> sorted = new ArrayList<>(getResources());
-        sorted.sort(null);
-        ClassSorterPlugin sorterPlugin = new ClassSorterPlugin(sorted);
-        ModulePool resourcePool = sorterPlugin.visit(getPool());
-        sorterPlugin.test(getPool(), resourcePool);
-    }
-
-    private String getModuleName(String p) {
-        return p.substring(1, p.indexOf('/', 1));
-    }
-
-    private void moduleSorting() throws Exception {
-        List<String> sorted = new ArrayList<>(getResources());
-        sorted.sort((s1, s2) -> -getModuleName(s1).compareTo(getModuleName(s2)));
-        ModuleSorterPlugin sorterPlugin = new ModuleSorterPlugin();
-        ModulePool resourcePool = sorterPlugin.visit(getPool());
-        sorterPlugin.test(getPool(), resourcePool);
-    }
-
-    private class ModuleSorterPlugin extends TestPlugin {
-
-        @Override
-        public void visit() {
-            for (AsmModulePool modulePool : getPools().getModulePools()) {
-                modulePool.setSorter(resources -> {
-                    List<String> sort = resources.entries()
-                            .map(ModuleEntry::getPath)
-                            .collect(Collectors.toList());
-                    sort.sort(null);
-                    return sort;
-                });
-            }
-            getPools().setModuleSorter(modules -> {
-                modules.sort((s1, s2) -> -s1.compareTo(s2));
-                return modules;
-            });
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            if (!isVisitCalled()) {
-                throw new AssertionError("Resources not visited");
-            }
-            List<String> sortedResourcePaths = outResources.entries()
-                    .map(ModuleEntry::getPath)
-                    .collect(Collectors.toList());
-
-            List<String> defaultResourceOrder = new ArrayList<>();
-            inResources.entries().forEach(r -> {
-                if (!inResources.contains(r)) {
-                    throw new AssertionError("Resource " + r.getPath() + " not in result pool");
-                }
-                defaultResourceOrder.add(r.getPath());
-            });
-            // Check that default sorting is not equal to sorted one
-            if (defaultResourceOrder.equals(sortedResourcePaths)) {
-                throw new AssertionError("Sorting not applied, default ordering");
-            }
-            // Check module order.
-            for (int i = 0; i < sortedResourcePaths.size() - 1; ++i) {
-                String first = sortedResourcePaths.get(i);
-                String p1 = getModuleName(first);
-                String second = sortedResourcePaths.get(i + 1);
-                String p2 = getModuleName(second);
-                if (p1.compareTo(p2) < 0 || p1.compareTo(p2) == 0 &&
-                        removeModule(first).compareTo(removeModule(second)) >= 0) {
-                    throw new AssertionError("Modules are not sorted properly: resources: " + first + " " + second);
-                }
-            }
-        }
-    }
-
-    private class ClassSorterPlugin extends TestPlugin {
-
-        private final List<String> expectedClassesOrder;
-
-        private ClassSorterPlugin(List<String> expectedClassesOrder) {
-            this.expectedClassesOrder = expectedClassesOrder;
-        }
-
-        @Override
-        public void visit() {
-            getPools().getGlobalPool().setSorter(
-                    (resources) -> expectedClassesOrder.stream()
-                            .map(resources::findEntry)
-                            .map(Optional::get)
-                            .map(ModuleEntry::getPath)
-                            .collect(Collectors.toList()));
-        }
-
-        @Override
-        public void test(ModulePool inResources, ModulePool outResources) throws Exception {
-            if (!isVisitCalled()) {
-                throw new AssertionError("Resources not visited");
-            }
-            List<String> sortedResourcePaths = outResources.entries()
-                    .map(ModuleEntry::getPath)
-                    .collect(Collectors.toList());
-
-            List<String> defaultResourceOrder = new ArrayList<>();
-            getPool().entries().forEach(r -> {
-                if (!getPool().contains(r)) {
-                    throw new AssertionError("Resource " + r.getPath() + " not in result pool");
-                }
-                defaultResourceOrder.add(r.getPath());
-            });
-            // Check that default sorting is not equal to sorted one
-            if (defaultResourceOrder.equals(sortedResourcePaths)) {
-                throw new AssertionError("Sorting not applied, default ordering");
-            }
-            // Check that sorted is equal to result.
-            if (!expectedClassesOrder.equals(sortedResourcePaths)) {
-                throw new AssertionError("Sorting not properly applied");
-            }
-        }
-    }
-}
--- a/test/tools/jlink/asmplugin/VisitorTest.java	Thu Jul 07 17:53:55 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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.
- */
-
-/*
- * Asm plugin testing.
- * @test
- * @summary Test visitors.
- * @author Andrei Eremeev
- * @modules java.base/jdk.internal.org.objectweb.asm
- *          jdk.jlink/jdk.tools.jlink.internal
- *          jdk.jlink/jdk.tools.jlink.internal.plugins.asm
- * @build AsmPluginTestBase
- * @run main VisitorTest
- */
-
-import java.io.IOException;
-import java.util.Collection;
-import java.util.function.Function;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
-import jdk.internal.org.objectweb.asm.ClassVisitor;
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Opcodes;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.ClassReaderVisitor;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFile;
-import jdk.tools.jlink.internal.plugins.asm.AsmPool.ResourceFileVisitor;
-import jdk.tools.jlink.internal.plugins.asm.AsmPools;
-import jdk.tools.jlink.plugin.ModuleEntry;
-import jdk.tools.jlink.plugin.ModulePool;
-
-public class VisitorTest extends AsmPluginTestBase {
-
-    public static void main(String[] args) throws Exception {
-        if (!isImageBuild()) {
-            System.err.println("Test not run. Not image build.");
-            return;
-        }
-        new VisitorTest().test();
-    }
-
-    @Override
-    public void test() throws Exception {
-        TestPlugin[] plugins = new TestPlugin[] {
-                new ClassVisitorPlugin("Class-global-pool", AsmPools::getGlobalPool),
-                new ClassVisitorPlugin("Class-module-pool", pools -> pools.getModulePool("java.base")),
-                new ResourceVisitorPlugin("Resource-global-pool", AsmPools::getGlobalPool),
-                new ResourceVisitorPlugin("Resource-module-pool", pools -> pools.getModulePool("java.base"))
-        };
-        for (TestPlugin p : plugins) {
-            System.err.println("Testing: " + p.getName());
-            ModulePool out = p.visit(getPool());
-            p.test(getPool(), out);
-        }
-    }
-
-    private static class CustomClassReaderVisitor implements ClassReaderVisitor {
-        private int amount = 0;
-        private int changed = 0;
-
-        @Override
-        public ClassWriter visit(ClassReader reader) {
-            if ((amount++ % 2) == 0) {
-                String className = reader.getClassName();
-                if (className.endsWith("module-info")) {
-                    return null;
-                }
-                ClassWriter cw = new ClassWriter(reader, ClassWriter.COMPUTE_FRAMES);
-                reader.accept(new ClassVisitor(Opcodes.ASM5, cw) {
-                    @Override
-                    public void visit(int i, int i1, String s, String s1, String s2, String[] strings) {
-                        super.visit(i, i1, s + "Changed", s1, s2, strings);
-                    }
-                }, ClassReader.EXPAND_FRAMES);
-                ++changed;
-                return cw;
-            } else {
-                return null;
-            }
-        }
-
-        public int getAmount() {
-            return amount;
-        }
-
-        public int getNumberOfChanged() {
-            return changed;
-        }
-    }
-
-    private static class CustomResourceFileVisitor implements ResourceFileVisitor {
-        private int amount = 0;
-        private int changed = 0;
-
-        @Override
-        public ResourceFile visit(ResourceFile resourceFile) {
-            if ((amount++ % 2) == 0) {
-                ++changed;
-                return new ResourceFile(resourceFile.getPath() + "Changed", resourceFile.getContent());
-            } else {
-                return null;
-            }
-        }
-
-        public int getAmount() {
-            return amount;
-        }
-
-        public int getNumberOfChanged() {
-            return changed;
-        }
-    }
-
-    public class ClassVisitorPlugin extends TestPlugin {
-
-        private final String name;
-        private final Function<AsmPools, AsmPool> getPool;
-        private final CustomClassReaderVisitor classReaderVisitor = new CustomClassReaderVisitor();
-
-        public ClassVisitorPlugin(String name, Function<AsmPools, AsmPool> getPool) {
-            this.name = name;
-            this.getPool = getPool;
-        }
-
-        @Override
-        public void visit() {
-            AsmPool pool = getPool.apply(getPools());
-            pool.visitClassReaders(classReaderVisitor);
-        }
-
-        @Override
-        public void test(ModulePool in, ModulePool out) throws Exception {
-            Collection<ModuleEntry> inClasses = getPool.apply(getPools()).getClasses();
-            if (inClasses.size() != classReaderVisitor.getAmount()) {
-                throw new AssertionError("Testing " + name + ". Number of visited classes. Expected: " +
-                        inClasses.size() + ", got: " + classReaderVisitor.getAmount());
-            }
-            Collection<ModuleEntry> outClasses = extractClasses(out);
-            int changedClasses = 0;
-            for (ModuleEntry r : outClasses) {
-                if (r.getPath().endsWith("Changed.class")) {
-                    ++changedClasses;
-                }
-            }
-            if (changedClasses != classReaderVisitor.getNumberOfChanged()) {
-                throw new AssertionError("Testing " + name + ". Changed classes. Expected: " + changedClasses +
-                        ", got: " + classReaderVisitor.getNumberOfChanged());
-            }
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-    }
-
-    public class ResourceVisitorPlugin extends TestPlugin {
-
-        private final String name;
-        private final Function<AsmPools, AsmPool> getPool;
-        private final CustomResourceFileVisitor resourceFileVisitor = new CustomResourceFileVisitor();
-
-        public ResourceVisitorPlugin(String name, Function<AsmPools, AsmPool> getPool) {
-            this.name = name;
-            this.getPool = getPool;
-        }
-
-        @Override
-        public void visit() {
-            AsmPool pool = getPool.apply(getPools());
-            pool.visitResourceFiles(resourceFileVisitor);
-        }
-
-        @Override
-        public void test(ModulePool in, ModulePool out) throws Exception {
-            Collection<ModuleEntry> inResources = getPool.apply(getPools()).getResourceFiles();
-            if (inResources.size() != resourceFileVisitor.getAmount()) {
-                throw new AssertionError("Testing " + name + ". Number of visited resources. Expected: " +
-                        inResources.size() + ", got: " + resourceFileVisitor.getAmount());
-            }
-            Collection<ModuleEntry> outResources = extractResources(out);
-            int changedClasses = 0;
-            for (ModuleEntry r : outResources) {
-                if (r.getPath().endsWith("Changed")) {
-                    ++changedClasses;
-                }
-            }
-            if (changedClasses != resourceFileVisitor.getNumberOfChanged()) {
-                throw new AssertionError("Testing " + name + ". Changed classes. Expected: " + changedClasses +
-                        ", got: " + resourceFileVisitor.getNumberOfChanged());
-            }
-        }
-
-        @Override
-        public String getName() {
-            return name;
-        }
-    }
-}