jdk/test/tools/jlink/JLinkOptimTest.java
changeset 39737 4da8463b3d33
parent 39736 f939432eb32a
parent 39559 0bd60e219fd0
child 39738 15fea8b870eb
--- a/jdk/test/tools/jlink/JLinkOptimTest.java	Fri Jul 08 17:36:34 2016 +0300
+++ /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);
-            }
-        }
-    }
-
-}