changeset 6:d183b6266b77

Add Redifintion micro with supporting classes
author ecaspole
date Wed, 20 Feb 2019 16:04:51 -0500
parents 92c55597888e
children 50cc9ad61a18
files micros-jdk11/pom.xml micros-jdk11/src/license/gpl_cpe/header.txt micros-jdk11/src/main/java/org/openjdk/bench/vm/jvmti/RedefineClassesWithAgent.java micros-uber/pom.xml micros-util/pom.xml micros-util/src/main/java/org/openjdk/bench/util/InMemoryJavaCompiler.java micros-util/src/main/java/org/openjdk/bench/util/ResourceUtil.java pom.xml redefineagent/pom.xml redefineagent/src/license/gpl_cpe/header.txt redefineagent/src/main/assembly/dist.xml redefineagent/src/main/java/org/openjdk/bench/vm/jvmti/RedefineClassHelper.java
diffstat 12 files changed, 1005 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/micros-jdk11/pom.xml	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2019, 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.openjdk</groupId>
+        <artifactId>jmh-jdk-microbenchmarks</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>micros-jdk11</artifactId>
+    <packaging>jar</packaging>
+    <name>OpenJDK Microbenchmark Corpus (JDK 11)</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>9</source>
+                    <target>9</target>
+                    <compilerArgs>
+                        <arg>--add-modules=java.base,java.compiler,java.instrument,jdk.jartool,jdk.attach</arg>
+                        <arg>--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED</arg>
+                        <arg>--add-exports=jdk.jartool/sun.tools.jar=ALL-UNNAMED</arg>
+                    </compilerArgs>
+
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>com.mycila.maven-license-plugin</groupId>
+                <artifactId>maven-license-plugin</artifactId>
+                <version>1.10.b1</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>format</goal>
+                        </goals>
+                        <phase>process-sources</phase>
+                        <configuration>
+                            <header>${project.basedir}/src/license/gpl_cpe/header.txt</header>
+                            <skipExistingHeaders>true</skipExistingHeaders>
+                            <strictCheck>true</strictCheck>
+                            <includes>
+                                <include>src/main/java</include>
+                            </includes>
+                            <mapping>
+                                <java>PHP</java>
+                            </mapping>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.3</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <transformers>
+                                <transformer
+                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
+                                    <mainClass>org.openjdk.jmh.Main</mainClass>
+                                </transformer>
+                                <transformer implementation="org.apache.maven.plugins.shade.resource.IncludeResourceTransformer">
+                                    <resource>redefineagent-1.0-SNAPSHOT.zip</resource>
+                                    <file>../redefineagent/target/redefineagent-1.0-SNAPSHOT.zip</file>
+                                </transformer>
+                            </transformers>
+                            <createDependencyReducedPom>false</createDependencyReducedPom>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <properties>
+        <jmh.version>1.21</jmh.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.openjdk</groupId>
+            <artifactId>redefineagent</artifactId>
+            <version>${project.version}</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.openjdk</groupId>
+            <artifactId>micros-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openjdk.jmh</groupId>
+            <artifactId>jmh-core</artifactId>
+            <version>${jmh.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.openjdk.jmh</groupId>
+            <artifactId>jmh-generator-annprocess</artifactId>
+            <version>${jmh.version}</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/micros-jdk11/src/license/gpl_cpe/header.txt	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,22 @@
+Copyright (c) 2014, 2019, 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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/micros-jdk11/src/main/java/org/openjdk/bench/vm/jvmti/RedefineClassesWithAgent.java	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package org.openjdk.bench.vm.jvmti;
+
+import org.openjdk.bench.util.InMemoryJavaCompiler;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.reflect.*;
+import java.lang.instrument.*;
+import java.lang.management.ManagementFactory;
+import com.sun.tools.attach.*;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.*;
+
+import org.openjdk.bench.util.*;
+import org.openjdk.jmh.annotations.*;
+
+// -Xlog:redefine+class+nmethod=debug is helpful when debugging
+@State(Scope.Thread)
+@Fork(jvmArgsAppend = {"-XX:CompileThreshold=100", "-Djdk.attach.allowAttachSelf=true", "-XX:+EnableDynamicAgentLoading"})
+public class RedefineClassesWithAgent {
+
+    @Param({"10", "50", "200"})
+    public int numberOfClasses = 50;
+
+    static byte[][] compiledClasses;
+    static byte[][] newCompiledClasses;
+    static int index = 0;
+
+    static String B(int count) {
+        return new String("public class B" + count + " {"
+                + "   static int intField;"
+                + "   public static void compiledMethod() { "
+                + "       intField++;"
+                + "   }"
+                + "}");
+    }
+
+    static String newB(int count) {
+        return new String("public class B" + count + " {"
+                + "   public static void compiledMethod() { "
+                + "       System.out.println(\"compiledMethod called " + count + "\");"
+                + "   }"
+                + "}");
+    }
+
+    // The agent jar is stored as a zip in the uber jar. It will be extracted into
+    // the cwd in its own directory.
+    private static final String agentZipInUberJar = "redefineagent-1.0-SNAPSHOT.zip";
+    private static final String agentJarLocationFromZip = "redefineagent-1.0-SNAPSHOT/redefineagent-1.0-SNAPSHOT.jar";
+
+    @Setup(Level.Trial)
+    public void setupAgent() throws FileNotFoundException, IOException,
+            AttachNotSupportedException, AgentLoadException, AgentInitializationException {
+        boolean extracted = ResourceUtil.extractIfNewer(agentZipInUberJar);
+
+        String thisVm = ManagementFactory.getRuntimeMXBean().getName();
+        int p = thisVm.indexOf('@');
+        String pid = thisVm.substring(0, p);
+
+        VirtualMachine vm = VirtualMachine.attach(pid);
+        vm.loadAgent(agentJarLocationFromZip, "");
+        vm.detach();
+    }
+
+    @Setup
+    public void setupClasses() throws Exception {
+        compiledClasses = new byte[numberOfClasses][];
+        newCompiledClasses = new byte[numberOfClasses][];
+        for (int i = 0; i < numberOfClasses; i++) {
+            compiledClasses[i] = InMemoryJavaCompiler.compile("B" + i, B(i));
+            newCompiledClasses[i] = InMemoryJavaCompiler.compile("B" + i, B(i));
+        }
+    }
+
+    static class RedefiningBenchLoader extends ClassLoader {
+
+        @Override
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            if (name.equals("B" + index)) {
+                assert compiledClasses[index]  != null;
+                return defineClass(name, compiledClasses[index] , 0, (compiledClasses[index]).length);
+            } else {
+                return super.findClass(name);
+            }
+        }
+    }
+
+    @Benchmark
+    @OutputTimeUnit(TimeUnit.MILLISECONDS)
+    @BenchmarkMode(Mode.AverageTime)
+    public void benchmark(ThreadState t) throws Exception {
+        assert t.defs != null && t.defs.length != 0;
+        assert t.defs.length == numberOfClasses;
+        RedefineClassHelper.instrumentation.redefineClasses(t.defs);
+    }
+
+
+    @State(Scope.Benchmark)
+    public static class ThreadState {
+
+        ClassDefinition[] defs;
+
+        @Setup(Level.Invocation)
+        public void setup() throws Exception {
+//            long start = System.currentTimeMillis();
+            ClassDefinition[] defs = new ClassDefinition[compiledClasses.length];
+
+            RedefineClassesWithAgent.RedefiningBenchLoader loader = new RedefineClassesWithAgent.RedefiningBenchLoader();
+            // Load and start all the classes.
+            for (index = 0; index < compiledClasses.length; index++) {
+                String name = new String("B" + index);
+                Class c = loader.findClass(name);
+
+                {
+                    Object o = c.newInstance();
+                    Method m = c.getMethod("compiledMethod");
+                    IntStream.range(0, 2000).parallel().forEach(x -> {
+                        try {
+                            m.invoke(o);
+                        } catch (Exception e) {
+                            System.out.println("Exception = " + e);
+                            assert true == false;
+                        }
+                    });
+                }
+
+                // Make class definition for redefinition
+                defs[index] = new ClassDefinition(c, newCompiledClasses[index]);
+                assert defs[index] != null;
+            }
+            this.defs = defs;
+            assert this.defs != null && this.defs.length != 0;
+//            long end = System.currentTimeMillis();
+//            System.out.println("# Setup:" + (end - start));
+        }
+
+        @TearDown(Level.Invocation)
+        public void tearDown() throws Exception {
+            this.defs = null;
+            System.gc();
+        }
+    }
+
+    static void runCompiledMethodMethods(Class c, int count) throws Exception {
+        // Run for a while so they compile.
+        Object o = c.newInstance();
+        Method m = c.getMethod("compiledMethod");
+        for (int i = 0; i < count; i++) {
+            m.invoke(o);
+        }
+    }
+}
--- a/micros-uber/pom.xml	Tue Nov 20 15:45:06 2018 -0500
+++ b/micros-uber/pom.xml	Wed Feb 20 16:04:51 2019 -0500
@@ -52,7 +52,7 @@
         <profile>
             <id>jdk9</id>
             <activation>
-                <jdk>[9,)</jdk>
+                <jdk>9</jdk>
             </activation>
             <dependencies>
                 <dependency>
@@ -67,6 +67,34 @@
                 </dependency>
             </dependencies>
         </profile>
+        <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>[11,)</jdk>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.openjdk</groupId>
+                    <artifactId>micros-jdk8</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.openjdk</groupId>
+                    <artifactId>micros-jdk9</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.openjdk</groupId>
+                    <artifactId>micros-jdk11</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+                <dependency>
+                    <groupId>org.openjdk</groupId>
+                    <artifactId>redefineagent</artifactId>
+                    <version>${project.version}</version>
+                </dependency>
+            </dependencies>
+        </profile>
     </profiles>
 
 </project>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/micros-util/pom.xml	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,48 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<!--
+ Copyright (c) 2019, 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.
+-->
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.openjdk</groupId>
+        <artifactId>jmh-jdk-microbenchmarks</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>micros-util</artifactId>
+    <packaging>jar</packaging>
+    <name>OpenJDK Microbenchmarks Utility Classes</name>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.1</version>
+                <configuration>
+                    <source>1.8</source>
+                    <target>1.8</target>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/micros-util/src/main/java/org/openjdk/bench/util/InMemoryJavaCompiler.java	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2013, 2019, 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.
+ */
+package org.openjdk.bench.util;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.tools.ForwardingJavaFileManager;
+import javax.tools.FileObject;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaCompiler.CompilationTask;
+import javax.tools.JavaFileObject;
+import javax.tools.JavaFileObject.Kind;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+
+/**
+ * {@code InMemoryJavaCompiler} can be used for compiling a {@link
+ * CharSequence} to a {@code byte[]}.
+ *
+ * The compiler will not use the file system at all, instead using a {@link
+ * ByteArrayOutputStream} for storing the byte code. For the source code, any
+ * kind of {@link CharSequence} can be used, e.g. {@link String}, {@link
+ * StringBuffer} or {@link StringBuilder}.
+ *
+ * <pre>
+ * {@code
+ * import org.openjdk.bench.util.InMemoryJavaCompiler;
+ *
+ * class Example {
+ *     public static void main(String[] args) {
+ *         String className = "Foo";
+ *         String sourceCode = "public class " + className + " {" +
+ *                             "    public void bar() {" +
+ *                             "        System.out.println("Hello from bar!");" +
+ *                             "    }" +
+ *                             "}";
+ *         byte[] byteCode = InMemoryJavaCompiler.compile(className, sourceCode);
+ *     }
+ * }
+ * }
+ * </pre>
+ */
+public class InMemoryJavaCompiler {
+    private static class MemoryJavaFileObject extends SimpleJavaFileObject {
+        private final String className;
+        private final CharSequence sourceCode;
+        private final ByteArrayOutputStream byteCode;
+
+        public MemoryJavaFileObject(String className, CharSequence sourceCode) {
+            super(URI.create("string:///" + className.replace('.','/') + Kind.SOURCE.extension), Kind.SOURCE);
+            this.className = className;
+            this.sourceCode = sourceCode;
+            this.byteCode = new ByteArrayOutputStream();
+        }
+
+        @Override
+        public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+            return sourceCode;
+        }
+
+        @Override
+        public OutputStream openOutputStream() throws IOException {
+            return byteCode;
+        }
+
+        public byte[] getByteCode() {
+            return byteCode.toByteArray();
+        }
+
+        public String getClassName() {
+            return className;
+        }
+    }
+
+    private static class FileManagerWrapper extends ForwardingJavaFileManager {
+        private static final Location PATCH_LOCATION = new Location() {
+            @Override
+            public String getName() {
+                return "patch module location";
+            }
+
+            @Override
+            public boolean isOutputLocation() {
+                return false;
+            }
+        };
+        private final MemoryJavaFileObject file;
+        private final String moduleOverride;
+
+        public FileManagerWrapper(MemoryJavaFileObject file, String moduleOverride) {
+            super(getCompiler().getStandardFileManager(null, null, null));
+            this.file = file;
+            this.moduleOverride = moduleOverride;
+        }
+
+        @Override
+        public JavaFileObject getJavaFileForOutput(Location location, String className,
+                                                   Kind kind, FileObject sibling)
+            throws IOException {
+            if (!file.getClassName().equals(className)) {
+                throw new IOException("Expected class with name " + file.getClassName() +
+                                      ", but got " + className);
+            }
+            return file;
+        }
+
+        @Override
+        public Location getLocationForModule(Location location, JavaFileObject fo) throws IOException {
+            if (fo == file && moduleOverride != null) {
+                return PATCH_LOCATION;
+            }
+            return super.getLocationForModule(location, fo);
+        }
+
+        @Override
+        public String inferModuleName(Location location) throws IOException {
+            if (location == PATCH_LOCATION) {
+                return moduleOverride;
+            }
+            return super.inferModuleName(location);
+        }
+
+        @Override
+        public boolean hasLocation(Location location) {
+            return super.hasLocation(location) || location == StandardLocation.PATCH_MODULE_PATH;
+        }
+
+    }
+
+    /**
+     * Compiles the class with the given name and source code.
+     *
+     * @param className The name of the class
+     * @param sourceCode The source code for the class with name {@code className}
+     * @param options additional command line options
+     * @throws RuntimeException if the compilation did not succeed
+     * @return The resulting byte code from the compilation
+     */
+    public static byte[] compile(String className, CharSequence sourceCode, String... options) {
+        MemoryJavaFileObject file = new MemoryJavaFileObject(className, sourceCode);
+        CompilationTask task = getCompilationTask(file, options);
+
+        if(!task.call()) {
+            throw new RuntimeException("Could not compile " + className + " with source code " + sourceCode);
+        }
+
+        return file.getByteCode();
+    }
+
+    private static JavaCompiler getCompiler() {
+        return ToolProvider.getSystemJavaCompiler();
+    }
+
+    private static CompilationTask getCompilationTask(MemoryJavaFileObject file, String... options) {
+        List<String> opts = new ArrayList<>();
+        String moduleOverride = null;
+        for (String opt : options) {
+            if (opt.startsWith("--patch-module=")) {
+                moduleOverride = opt.substring("--patch-module=".length());
+            } else {
+                opts.add(opt);
+            }
+        }
+        return getCompiler().getTask(null, new FileManagerWrapper(file, moduleOverride), null, opts, null, Arrays.asList(file));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/micros-util/src/main/java/org/openjdk/bench/util/ResourceUtil.java	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+package org.openjdk.bench.util;
+
+import java.io.BufferedInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.nio.file.attribute.FileTime;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public final class ResourceUtil {
+
+    public static boolean extractIfNewer(String zipResource) throws FileNotFoundException, IOException {
+        return extractIfNewer(zipResource, "");
+    }
+
+    public static boolean extractIfNewer(String zipResource, String dstFolder) throws FileNotFoundException, IOException {
+        Path root = Paths.get(dstFolder).toAbsolutePath();
+        try ( ZipInputStream zis = new ZipInputStream(new BufferedInputStream(ResourceUtil.class.getClassLoader().getResourceAsStream(zipResource)))) {
+            byte[] buf = new byte[4096];
+            for (ZipEntry entry; (entry = zis.getNextEntry()) != null;) {
+                Path dst = root.resolve(Paths.get(entry.getName()));
+                if (!Files.exists(dst) || Files.getLastModifiedTime(dst).toMillis() != entry.getTime()) {
+                    //System.out.println(dst);
+                    if (entry.isDirectory()) {
+                        Files.createDirectories(dst);
+                    } else {
+                        try ( OutputStream out = Files.newOutputStream(dst)) {
+                            for (int len; (len = zis.read(buf)) > 0; out.write(buf, 0, len));
+                        }
+                    }
+                    Files.setLastModifiedTime(dst, FileTime.fromMillis(entry.getTime()));
+                } else {
+                    return false;
+                }
+            }
+            return true;
+        }
+    }
+
+    public static void clearExtracted(String zipResource) throws FileNotFoundException, IOException {
+        clearExtracted(zipResource, "");
+    }
+
+    public static void clearExtracted(String zipResource, String dstFolder) throws FileNotFoundException, IOException {
+        Path root = Paths.get(dstFolder).toAbsolutePath();
+        try ( ZipInputStream zis = new ZipInputStream(new BufferedInputStream(ResourceUtil.class.getClassLoader().getResourceAsStream(zipResource)))) {
+            for (ZipEntry entry; (entry = zis.getNextEntry()) != null;) {
+                Path dst = root.resolve(Paths.get(entry.getName()));
+                if (Files.exists(dst)) {
+                    //System.out.println(dst);
+                    if (entry.isDirectory()) {
+                        Files.walkFileTree(dst, DEL);
+                    } else {
+                        Files.delete(dst);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final FileVisitor<Path> DEL = new SimpleFileVisitor<Path>() {
+
+        @Override
+        public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
+            Files.delete(file);
+            return FileVisitResult.CONTINUE;
+        }
+
+        @Override
+        public FileVisitResult postVisitDirectory(Path directory, IOException e) throws IOException {
+            Files.delete(directory);
+            return FileVisitResult.CONTINUE;
+        }
+    };
+}
--- a/pom.xml	Tue Nov 20 15:45:06 2018 -0500
+++ b/pom.xml	Wed Feb 20 16:04:51 2019 -0500
@@ -60,6 +60,20 @@
             </modules>
         </profile>
         <profile>
+            <id>jdk11</id>
+            <activation>
+                <jdk>[11,)</jdk>
+            </activation>
+            <modules>
+                <module>micros-uber</module>
+                <module>micros-jdk8</module>
+                <module>micros-jdk9</module>
+                <module>micros-jdk11</module>
+                <module>micros-util</module>
+                <module>redefineagent</module>
+            </modules>
+        </profile>
+        <profile>
             <id>maven-3</id>
             <activation>
                 <file>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/redefineagent/pom.xml	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ Copyright (c) 2019, 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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.openjdk</groupId>
+        <artifactId>jmh-jdk-microbenchmarks</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>redefineagent</artifactId>
+    <packaging>jar</packaging>
+    <name>OpenJDK Microbenchmark Corpus (redefineagent jar)</name>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>3.8.0</version>
+                <configuration>
+                    <source>9</source>
+                    <target>9</target>
+                    <compilerArgs>
+                        <arg>--add-modules=java.base,java.compiler,java.instrument,jdk.jartool</arg>
+                        <arg>--add-exports=java.base/jdk.internal.misc=ALL-UNNAMED</arg>
+                        <arg>--add-exports=jdk.jartool/sun.tools.jar=ALL-UNNAMED</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <version>2.4</version>
+                <configuration>
+                    <archive>
+                        <!-- Do not waste time compressing, maven-shade-plugin will compress the final JAR -->
+                        <compress>false</compress>
+                        <manifestEntries>
+                            <Premain-Class>org.openjdk.bench.vm.jvmti.RedefineClassHelper</Premain-Class>
+                            <Agent-Class>org.openjdk.bench.vm.jvmti.RedefineClassHelper</Agent-Class>
+                            <Can-Redefine-Classes>true</Can-Redefine-Classes>
+                        </manifestEntries>
+                    </archive>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-shade-plugin</artifactId>
+                <version>2.3</version>
+                <executions>
+                    <execution>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>shade</goal>
+                        </goals>
+                        <configuration>
+                            <artifactSet>
+                                <excludes>
+                                    <exclude>org.openjdk.jmh:*</exclude>
+                                    <exclude>org.sonatype.aether:*</exclude>
+                                    <exclude>org.codehaus.plexus:*</exclude>
+                                    <exclude>org.sonatype.plexus:*</exclude>
+                                    <exclude>junit:*</exclude>
+                                    <exclude>org.ow2.asm:*</exclude>
+                                    <exclude>commons-io:commons-io</exclude>
+                                    <exclude>org.openjdk.jmh:jmh-core:*</exclude>
+                                    <exclude>org.openjdk.jmh:jmh-generator-annprocess:*</exclude>
+                                    <exclude>org.vafer:jdependency</exclude>
+                                    <exclude>org.ow2.asm:asm-analysis</exclude>
+                                    <exclude>org.ow2.asm:asm-util</exclude>
+                                    <exclude>com.google.guava:guava</exclude>
+                                    <exclude>net.sf.jopt-simple:jopt-simple</exclude>
+                                    <exclude>org.apache.commons:commons-math3</exclude>
+                                </excludes>
+                            </artifactSet>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-assembly-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>assembly</id>
+                        <phase>package</phase>
+                        <goals>
+                            <goal>single</goal>
+                        </goals>
+                        <configuration>
+                            <descriptors>
+                                <descriptor>
+                                    src/main/assembly/dist.xml
+                                </descriptor>
+                            </descriptors>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>com.mycila.maven-license-plugin</groupId>
+                <artifactId>maven-license-plugin</artifactId>
+                <version>1.10.b1</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>format</goal>
+                        </goals>
+                        <phase>process-sources</phase>
+                        <configuration>
+                            <header>${project.basedir}/src/license/gpl_cpe/header.txt</header>
+                            <skipExistingHeaders>true</skipExistingHeaders>
+                            <strictCheck>true</strictCheck>
+                            <includes>
+                                <include>src/main/java</include>
+                            </includes>
+                            <mapping>
+                                <java>PHP</java>
+                            </mapping>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+    <dependencies>
+        <dependency>
+            <groupId>org.openjdk</groupId>
+            <artifactId>micros-util</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/redefineagent/src/license/gpl_cpe/header.txt	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,22 @@
+Copyright (c) 2014, 2019, 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.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/redefineagent/src/main/assembly/dist.xml	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (c) 2019, 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.
+-->
+
+<assembly>
+    <!-- <id>dist</id> -->
+    <formats>
+        <format>zip</format>
+    </formats>
+    <files>
+        <file>
+            <source>target/${artifactId}-${version}.jar</source>
+            <outputDirectory></outputDirectory>
+            <fileMode>0644</fileMode>
+        </file>
+    </files>
+</assembly>
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/redefineagent/src/main/java/org/openjdk/bench/vm/jvmti/RedefineClassHelper.java	Wed Feb 20 16:04:51 2019 -0500
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2014, 2019, 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.
+ */
+package org.openjdk.bench.vm.jvmti;
+
+import java.lang.instrument.*;
+
+import org.openjdk.bench.util.*;
+
+/*
+ * Helper class to write tests that redefine classes based on hotspot jtregs.
+ */
+public class RedefineClassHelper {
+
+    public static Instrumentation instrumentation;
+    public static void premain(String agentArgs, Instrumentation inst) {
+        instrumentation = inst;
+//        System.out.println("RedefineClassHelper.premain");
+    }
+
+    public static void agentmain(String agentArgs, Instrumentation inst) {
+        instrumentation = inst;
+//        System.out.println("RedefineClassHelper.agentmain");
+    }
+
+    /**
+     * Redefine a class
+     *
+     * @param clazz Class to redefine
+     * @param javacode String with the new java code for the class to be redefined
+     */
+    public static void redefineClass(Class clazz, String javacode) throws Exception {
+        byte[] bytecode = InMemoryJavaCompiler.compile(clazz.getName(), javacode);
+        redefineClass(clazz, bytecode);
+    }
+
+    /**
+     * Redefine a class
+     *
+     * @param clazz Class to redefine
+     * @param bytecode byte[] with the new class
+     */
+    public static void redefineClass(Class clazz, byte[] bytecode) throws Exception {
+        instrumentation.redefineClasses(new ClassDefinition(clazz, bytecode));
+    }
+}