--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins.properties Thu Jul 07 17:53:55 2016 +0900
+++ b/jdk/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/jdk/src/jdk.jlink/share/classes/module-info.java Thu Jul 07 17:53:55 2016 +0900
+++ b/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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/jdk/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;
- }
- }
-}