8220744: Move RedefineTests to from runtime to serviceability
Summary: move tests out of runtime to jvmti/RedefineClasses
Reviewed-by: sspitsyn, dcubed, cjplummer, hseigel, mseledtsov
--- a/test/hotspot/jtreg/TEST.groups Tue Mar 19 14:32:41 2019 -0400
+++ b/test/hotspot/jtreg/TEST.groups Tue Mar 19 14:22:47 2019 -0400
@@ -281,11 +281,6 @@
-runtime/modules/ModuleStress/ExportModuleStressTest.java \
-runtime/modules/ModuleStress/ModuleStressGC.java \
-runtime/NMT \
- -runtime/RedefineObject/TestRedefineObject.java \
- -runtime/RedefineTests/RedefineLeak.java \
- -runtime/RedefineTests/RedefinePreviousVersions.java \
- -runtime/RedefineTests/RedefineRunningMethods.java \
- -runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java \
-runtime/ReservedStack \
-runtime/SelectionResolution/AbstractMethodErrorTest.java \
-runtime/SelectionResolution/IllegalAccessErrorTest.java \
@@ -329,6 +324,12 @@
tier1_serviceability = \
serviceability/dcmd/compiler \
-serviceability/dcmd/compiler/CompilerQueueTest.java \
+ serviceability/jvmti/RedefineClasses \
+ -serviceability/jvmti/RedefineClasses/RedefineLeak.java \
+ -serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java \
+ -serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java \
+ -serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java \
+ -serviceability/jvmti/RedefineClasses/TestRedefineObject.java \
serviceability/logging \
serviceability/sa \
-serviceability/sa/ClhsdbScanOops.java \
--- a/test/hotspot/jtreg/runtime/RedefineObject/Agent.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,83 +0,0 @@
-/*
- * Copyright (c) 2013, 2014, 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.security.*;
-import java.lang.instrument.*;
-import java.lang.reflect.*;
-
-public class Agent implements ClassFileTransformer {
- public synchronized byte[] transform(final ClassLoader classLoader,
- final String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer) {
- System.out.println("Transforming class " + className);
- return classfileBuffer;
- }
-
- public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
-
- try {
- instrumentation.retransformClasses(to_redefine);
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- public static void premain(String agentArgs, Instrumentation instrumentation) {
- Agent transformer = new Agent();
- instrumentation.addTransformer(transformer, true);
-
- // Redefine java/lang/Object and java/lang/reflect/Method.invoke and
- // java/lang/ClassLoader
- Class object_class = Object.class;
- redefine(agentArgs, instrumentation, object_class);
-
- Class method_class = Method.class;
- redefine(agentArgs, instrumentation, method_class);
-
- Class loader_class = ClassLoader.class;
- redefine(agentArgs, instrumentation, loader_class);
-
- instrumentation.removeTransformer(transformer);
- }
-
- public static void main(String[] args) {
- byte[] ba = new byte[0];
-
- // If it survives 100 GC's, it's good.
- for (int i = 0; i < 100 ; i++) {
- System.gc();
- ba.clone();
- }
- try {
- // Use java/lang/reflect/Method.invoke to call
- WalkThroughInvoke a = new WalkThroughInvoke();
- Class aclass = WalkThroughInvoke.class;
- Method m = aclass.getMethod("stackWalk");
- m.invoke(a);
- } catch (Exception x) {
- x.printStackTrace();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineObject/TestRedefineObject.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,59 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- *
- * 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.PrintWriter;
-
-import jdk.test.lib.JDKToolFinder;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-/*
- * Test to redefine java/lang/Object and verify that it doesn't crash on vtable
- * call on basic array type.
- * Test to redefine java/lang/ClassLoader and java/lang/reflect/Method to make
- * sure cached versions used afterward are the current version.
- *
- * @test
- * @bug 8005056
- * @bug 8009728
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.instrument
- * java.management
- * @build Agent
- * @run driver ClassFileInstaller Agent
- * @run main TestRedefineObject
- * @run main/othervm -javaagent:agent.jar -Xlog:redefine+class+load=debug,redefine+class+timer=info Agent
- */
-public class TestRedefineObject {
- public static void main(String[] args) throws Exception {
-
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: Agent");
- pw.println("Can-Retransform-Classes: true");
- pw.close();
-
- ProcessBuilder pb = new ProcessBuilder();
- pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"});
- pb.start().waitFor();
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineObject/WalkThroughInvoke.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,38 +0,0 @@
-/*
- * Copyright (c) 2013, 2018, 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.lang.reflect.*;
-
-public class WalkThroughInvoke {
- public void stackWalk() {
- try {
- Class b = Object.class;
- SecurityManager sm = new SecurityManager();
- // Walks the stack with Method.invoke in the stack (which is the
- // purpose of the test) before it gets an AccessControlException.
- sm.checkPermission(new RuntimePermission("accessDeclaredMembers"));
- } catch (java.security.AccessControlException e) {
- // Ignoring an 'AccessControlException' exception since
- // it is expected as part of this test.
- }
- }
-};
--- a/test/hotspot/jtreg/runtime/RedefineTests/ModifyAnonymous.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,203 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, 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
- * @library /test/lib
- * @summary Test that retransforming and redefining anonymous classes gets UnmodifiableClassException
- * @modules java.base/jdk.internal.misc
- * @modules java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main ModifyAnonymous buildagent
- * @run main/othervm -javaagent:redefineagent.jar ModifyAnonymous
- */
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.PrintWriter;
-import java.lang.RuntimeException;
-import java.lang.instrument.ClassDefinition;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-
-import jdk.test.lib.compiler.InMemoryJavaCompiler;
-
-public class ModifyAnonymous {
-
- public static class LambdaTransformer implements ClassFileTransformer {
- @Override
- public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
- return null;
- }
- }
-
- static Instrumentation inst = null;
- static volatile boolean done = false;
-
- public static void premain(String args, Instrumentation instrumentation) {
-
- inst = instrumentation;
- System.out.println("javaagent in da house!");
- instrumentation.addTransformer(new LambdaTransformer());
- }
-
- private static void buildAgent() {
- try {
- ClassFileInstaller.main("ModifyAnonymous");
- } catch (Exception e) {
- throw new RuntimeException("Could not write agent classfile", e);
- }
-
- try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: ModifyAnonymous");
- pw.println("Agent-Class: ModifyAnonymous");
- pw.println("Can-Retransform-Classes: true");
- pw.println("Can-Redefine-Classes: true");
- pw.close();
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write manifest file for the agent", e);
- }
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "ModifyAnonymous.class" })) {
- throw new RuntimeException("Could not write the agent jar file");
- }
- }
-
- public static class InstanceMethodCallSiteApp {
-
- public static void test() throws InterruptedException {
- for (int i = 0; i < 2; i++) {
- InstanceMethodCallSiteApp app = new InstanceMethodCallSiteApp();
- Runnable r = app::doWork; // this creates an anonymous class
- while (!done) {
- r.run();
- Thread.sleep(10);
- }
- }
- }
-
- public void doWork() {
- System.out.print(".");
- }
- }
-
- static void runTest() {
- PrintWriter pw;
- String logName = System.getProperty("test.classes") +
- File.separator + "loadedClasses.log";
- // Create a log file to capture the names of the classes in the
- // allLoadedClasses array. The log file is for assisting in debugging
- // in case a null class is encountered in the allLoadedClasses array.
- try {
- pw = new PrintWriter(new FileOutputStream(
- new File(logName), true));
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write loaded classes to log", e);
- }
- while (!done) {
- Class[] allLoadedClasses = inst.getAllLoadedClasses();
- int len = allLoadedClasses.length;
- pw.println(" allLoadedClasses length: " + len);
- for (int idx = 0; idx < len; idx++) {
- Class cls = allLoadedClasses[idx];
- pw.println(" " + idx + " " +
- ((cls != null) ? cls.getName() : "null"));
- }
- for (int idx = 0; idx < len; idx++) {
- Class clazz = allLoadedClasses[idx];
- if (clazz == null) {
- pw.flush();
- pw.close();
- throw new RuntimeException("null class encountered");
- }
- final String name = clazz.getName();
- if (name.contains("$$Lambda$") && name.contains("App")) {
- if (inst.isModifiableClass(clazz)) {
- pw.flush();
- pw.close();
- throw new RuntimeException ("Class should not be modifiable");
- }
- // Try to modify them anyway.
- try {
- System.out.println("retransform called for " + name);
- inst.retransformClasses(clazz);
- } catch(java.lang.instrument.UnmodifiableClassException t) {
- System.out.println("PASSED: expecting UnmodifiableClassException");
- t.printStackTrace();
- }
- try {
- System.out.println("redefine called for " + name);
- String newclass = "class Dummy {}";
- byte[] bytecode = InMemoryJavaCompiler.compile("Dummy", newclass);
- ClassDefinition cld = new ClassDefinition(clazz, bytecode);
- inst.redefineClasses(new ClassDefinition[] { cld });
- } catch(java.lang.instrument.UnmodifiableClassException t) {
- System.out.println("PASSED: expecting UnmodifiableClassException");
- t.printStackTrace();
- } catch(java.lang.ClassNotFoundException e) {
- pw.flush();
- pw.close();
- throw new RuntimeException ("ClassNotFoundException thrown");
- }
- done = true;
- }
- }
- }
- pw.flush();
- pw.close();
- }
-
- public static void main(String argv[]) throws InterruptedException, RuntimeException {
- if (argv.length == 1 && argv[0].equals("buildagent")) {
- buildAgent();
- return;
- }
-
- if (inst == null) {
- throw new RuntimeException("Instrumentation object was null");
- }
-
- new Thread() {
- public void run() {
- runTest();
- }
- }.start();
-
- // Test that NCDFE is not thrown for anonymous class:
- // ModifyAnonymous$InstanceMethodCallSiteApp$$Lambda$18
- try {
- ModifyAnonymous test = new ModifyAnonymous();
- InstanceMethodCallSiteApp.test();
- } catch (NoClassDefFoundError e) {
- throw new RuntimeException("FAILED: NoClassDefFoundError thrown for " + e.getMessage());
- }
- System.out.println("PASSED: NoClassDefFound error not thrown");
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineAddLambdaExpression.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2018, 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
- * @bug 8193524
- * @summary Redefine a class' public static method that contains a lambda expression
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression
- */
-
-interface MathOperation {
- public int operation(int a, int b);
-}
-
-class B {
- public static int operate(int a, int b, MathOperation mathOperation) {
- return mathOperation.operation(a, b);
- }
- static int test_math(String p) {
- MathOperation addition = (int a, int b) -> a + b;
- return operate(10, 5, addition);
- }
-}
-
-public class RedefineAddLambdaExpression {
-
- public static String newB =
- "class B {" +
- " public static int operate(int a, int b, MathOperation mathOperation) {" +
- " return mathOperation.operation(a, b);" +
- " }" +
- " static int test_math(String p) {" +
- " MathOperation addition = (int a, int b) -> a + b;" +
- " System.out.println(p + \" from class B's test_math method\");" +
- " MathOperation subtraction = (int a, int b) -> a - b;" +
- " return operate(10, 5, subtraction);" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- int res = B.test_math("Hello");
- System.out.println("Result = " + res);
- if (res != 15) {
- throw new Error("test_math returned " + res + " expected " + 15);
- }
- RedefineClassHelper.redefineClass(B.class, newB);
-
- res = B.test_math("Hello");
- if (res != 5)
- throw new Error("test_math returned " + res + " expected " + 5);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineAnnotations.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,414 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, 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
- * @library /test/lib
- * @summary Test that type annotations are retained after a retransform
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineAnnotations buildagent
- * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
- */
-
-import static jdk.test.lib.Asserts.assertTrue;
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.lang.NoSuchFieldException;
-import java.lang.NoSuchMethodException;
-import java.lang.RuntimeException;
-import java.lang.annotation.Annotation;
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.lang.reflect.AnnotatedArrayType;
-import java.lang.reflect.AnnotatedParameterizedType;
-import java.lang.reflect.AnnotatedType;
-import java.lang.reflect.AnnotatedWildcardType;
-import java.lang.reflect.Executable;
-import java.lang.reflect.TypeVariable;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-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.FieldVisitor;
-import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE_USE)
-@interface TestAnn {
- String site();
-}
-
-public class RedefineAnnotations {
- static Instrumentation inst;
- public static void premain(String agentArgs, Instrumentation inst) {
- RedefineAnnotations.inst = inst;
- }
-
- static class Transformer implements ClassFileTransformer {
-
- public byte[] asm(ClassLoader loader, String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
-
- ClassWriter cw = new ClassWriter(0);
- ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
- ClassReader cr = new ClassReader(classfileBuffer);
- cr.accept(cv, 0);
- return cw.toByteArray();
- }
-
- public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
-
- LinkedList<F> fields = new LinkedList<>();
-
- public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
- super(api, cv);
- }
-
- @Override public FieldVisitor visitField(int access, String name,
- String desc, String signature, Object value) {
- if (name.startsWith("dummy")) {
- // Remove dummy field
- fields.addLast(new F(access, name, desc, signature, value));
- return null;
- }
- return cv.visitField(access, name, desc, signature, value);
- }
-
- @Override public void visitEnd() {
- F f;
- while ((f = fields.pollFirst()) != null) {
- // Re-add dummy fields
- cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
- }
- }
-
- private class F {
- private int access;
- private String name;
- private String desc;
- private String signature;
- private Object value;
- F(int access, String name, String desc, String signature, Object value) {
- this.access = access;
- this.name = name;
- this.desc = desc;
- this.signature = signature;
- this.value = value;
- }
- }
- }
-
- @Override public byte[] transform(ClassLoader loader, String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
-
- if (className.contains("TypeAnnotatedTestClass")) {
- try {
- // Here we remove and re-add the dummy fields. This shuffles the constant pool
- return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
- } catch (Throwable e) {
- // The retransform native code that called this method does not propagate
- // exceptions. Instead of getting an uninformative generic error, catch
- // problems here and print it, then exit.
- e.printStackTrace();
- System.exit(1);
- }
- }
- return null;
- }
- }
-
- private static void buildAgent() {
- try {
- ClassFileInstaller.main("RedefineAnnotations");
- } catch (Exception e) {
- throw new RuntimeException("Could not write agent classfile", e);
- }
-
- try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: RedefineAnnotations");
- pw.println("Agent-Class: RedefineAnnotations");
- pw.println("Can-Retransform-Classes: true");
- pw.close();
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write manifest file for the agent", e);
- }
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
- throw new RuntimeException("Could not write the agent jar file");
- }
- }
-
- public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
- if (argv.length == 1 && argv[0].equals("buildagent")) {
- buildAgent();
- return;
- }
-
- if (inst == null) {
- throw new RuntimeException("Instrumentation object was null");
- }
-
- RedefineAnnotations test = new RedefineAnnotations();
- test.testTransformAndVerify();
- }
-
- // Class type annotations
- private Annotation classTypeParameterTA;
- private Annotation extendsTA;
- private Annotation implementsTA;
-
- // Field type annotations
- private Annotation fieldTA;
- private Annotation innerTA;
- private Annotation[] arrayTA = new Annotation[4];
- private Annotation[] mapTA = new Annotation[5];
-
- // Method type annotations
- private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
-
- private void testTransformAndVerify()
- throws NoSuchFieldException, NoSuchMethodException {
-
- Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
- Class<?> myClass = c;
-
- /*
- * Verify that the expected annotations are where they should be before transform.
- */
- verifyClassTypeAnnotations(c);
- verifyFieldTypeAnnotations(c);
- verifyMethodTypeAnnotations(c);
-
- try {
- inst.addTransformer(new Transformer(), true);
- inst.retransformClasses(myClass);
- } catch (UnmodifiableClassException e) {
- throw new RuntimeException(e);
- }
-
- /*
- * Verify that the expected annotations are where they should be after transform.
- * Also verify that before and after are equal.
- */
- verifyClassTypeAnnotations(c);
- verifyFieldTypeAnnotations(c);
- verifyMethodTypeAnnotations(c);
- }
-
- private void verifyClassTypeAnnotations(Class c) {
- Annotation anno;
-
- anno = c.getTypeParameters()[0].getAnnotations()[0];
- verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
- classTypeParameterTA = anno;
-
- anno = c.getAnnotatedSuperclass().getAnnotations()[0];
- verifyTestAnn(extendsTA, anno, "extends");
- extendsTA = anno;
-
- anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
- verifyTestAnn(implementsTA, anno, "implements");
- implementsTA = anno;
- }
-
- private void verifyFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- verifyBasicFieldTypeAnnotations(c);
- verifyInnerFieldTypeAnnotations(c);
- verifyArrayFieldTypeAnnotations(c);
- verifyMapFieldTypeAnnotations(c);
- }
-
- private void verifyBasicFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
- verifyTestAnn(fieldTA, anno, "field");
- fieldTA = anno;
- }
-
- private void verifyInnerFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
- Annotation anno = at.getAnnotations()[0];
- verifyTestAnn(innerTA, anno, "inner");
- innerTA = anno;
- }
-
- private void verifyArrayFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- Annotation anno;
- AnnotatedType at;
-
- at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
- anno = at.getAnnotations()[0];
- verifyTestAnn(arrayTA[0], anno, "array1");
- arrayTA[0] = anno;
-
- for (int i = 1; i <= 3; i++) {
- at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
- anno = at.getAnnotations()[0];
- verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
- arrayTA[i] = anno;
- }
- }
-
- private void verifyMapFieldTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
-
- Annotation anno;
- AnnotatedType atBase;
- AnnotatedType atParameter;
- atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
-
- anno = atBase.getAnnotations()[0];
- verifyTestAnn(mapTA[0], anno, "map1");
- mapTA[0] = anno;
-
- atParameter =
- ((AnnotatedParameterizedType) atBase).
- getAnnotatedActualTypeArguments()[0];
- anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
- verifyTestAnn(mapTA[1], anno, "map2");
- mapTA[1] = anno;
-
- anno =
- ((AnnotatedWildcardType) atParameter).
- getAnnotatedUpperBounds()[0].getAnnotations()[0];
- verifyTestAnn(mapTA[2], anno, "map3");
- mapTA[2] = anno;
-
- atParameter =
- ((AnnotatedParameterizedType) atBase).
- getAnnotatedActualTypeArguments()[1];
- anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
- verifyTestAnn(mapTA[3], anno, "map4");
- mapTA[3] = anno;
-
- anno =
- ((AnnotatedParameterizedType) atParameter).
- getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
- verifyTestAnn(mapTA[4], anno, "map5");
- mapTA[4] = anno;
- }
-
- private void verifyMethodTypeAnnotations(Class c)
- throws NoSuchFieldException, NoSuchMethodException {
- Annotation anno;
- Executable typeAnnotatedMethod =
- c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
-
- anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
- verifyTestAnn(returnTA, anno, "return");
- returnTA = anno;
-
- anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
- verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
- methodTypeParameterTA = anno;
-
- anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
- verifyTestAnn(formalParameterTA, anno, "formalParameter");
- formalParameterTA = anno;
-
- anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
- verifyTestAnn(throwsTA, anno, "throws");
- throwsTA = anno;
- }
-
- private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
- verifyTestAnnSite(anno, expectedSite);
-
- // When called before transform verifyAgainst will be null, when called
- // after transform it will be the annotation from before the transform
- if (verifyAgainst != null) {
- assertTrue(anno.equals(verifyAgainst),
- "Annotations do not match before and after." +
- " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
- }
- }
-
- private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
- String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
- assertTrue(testAnn.toString().equals(expectedAnn),
- "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
- }
-
- public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
- extends @TestAnn(site="extends") Thread
- implements @TestAnn(site="implements") Runnable {
-
- public @TestAnn(site="field") boolean typeAnnotatedBoolean;
-
- public
- RedefineAnnotations.
- @TestAnn(site="inner") TypeAnnotatedTestClass
- typeAnnotatedInner;
-
- public
- @TestAnn(site="array4") boolean
- @TestAnn(site="array1") []
- @TestAnn(site="array2") []
- @TestAnn(site="array3") []
- typeAnnotatedArray;
-
- public @TestAnn(site="map1") Map
- <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
- @TestAnn(site="map4") List<@TestAnn(site="map5") Object>> typeAnnotatedMap;
-
- public int dummy1;
- public int dummy2;
- public int dummy3;
-
- @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
- typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
- throws @TestAnn(site="throws") ClassNotFoundException {
-
- @TestAnn(site="local_variable_type") int foo = 0;
- throw new ClassNotFoundException();
- }
-
- public void run() {}
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDeleteJmethod.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @bug 8181171
- * @summary Test deleting static method pointing to by a jmethod
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod
- */
-
-class B {
- private static int deleteMe() { System.out.println("deleteMe called"); return 5; }
- public static int callDeleteMe() { return deleteMe(); }
-}
-
-public class RedefineDeleteJmethod {
-
- public static String newB =
- "class B {" +
- "public static int callDeleteMe() { return 6; }" +
- "}";
-
- public static String newerB =
- "class B {" +
- "private static int deleteMe() { System.out.println(\"deleteMe (2) called\"); return 7; }" +
- "public static int callDeleteMe() { return deleteMe(); }" +
- "}";
-
-
- static {
- System.loadLibrary("RedefineDeleteJmethod");
- }
-
- static native int jniCallDeleteMe();
-
- static void test(int expected, boolean nsme_expected) throws Exception {
- // Call through static method
- int res = B.callDeleteMe();
- System.out.println("Result = " + res);
- if (res != expected) {
- throw new Error("returned " + res + " expected " + expected);
- }
-
- // Call through jmethodID, saved from first call.
- try {
- res = jniCallDeleteMe();
- if (nsme_expected) {
- throw new RuntimeException("Failed, NoSuchMethodError expected");
- }
- if (res != expected) {
- throw new Error("returned " + res + " expected " + expected);
- }
- } catch (NoSuchMethodError ex) {
- if (!nsme_expected) {
- throw new RuntimeException("Failed, NoSuchMethodError not expected");
- }
- System.out.println("Passed, NoSuchMethodError expected");
- }
- }
-
- public static void main(String[] args) throws Exception {
- test(5, false);
- RedefineClassHelper.redefineClass(B.class, newB);
- test(6, true);
- RedefineClassHelper.redefineClass(B.class, newerB);
- test(7, true);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineDoubleDelete.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,91 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, 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
- * @bug 8178870 8010319
- * @summary Redefine class with CFLH twice to test deleting the cached_class_file
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
- */
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
-class RedefineDoubleDelete_B {
- int faa() { System.out.println("foo"); return 1; }
-}
-
-public class RedefineDoubleDelete {
-
- // Class gets a redefinition error because it adds a data member
- public static String newB =
- "class RedefineDoubleDelete_B {" +
- " int count1 = 0;" +
- "}";
-
- public static String newerB =
- "class RedefineDoubleDelete_B { " +
- " int faa() { System.out.println(\"baa\"); return 2; }" +
- "}";
-
- public static void main(String args[]) throws Exception {
-
- RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
- int val = b.faa();
- if (val != 1) {
- throw new RuntimeException("return value wrong " + val);
- }
-
- // Redefine B twice to get cached_class_file in both B scratch classes
- try {
- RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
- } catch (java.lang.UnsupportedOperationException e) {
- // this is expected
- }
- try {
- RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
- } catch (java.lang.UnsupportedOperationException e) {
- // this is expected
- }
-
- // Do a full GC.
- System.gc();
-
- // Redefine with a compatible class
- RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
- val = b.faa();
- if (val != 2) {
- throw new RuntimeException("return value wrong " + val);
- }
-
- // Do another full GC to clean things up.
- System.gc();
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineFinalizer.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,71 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, 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
- * @bug 6904403 8010319
- * @summary Don't assert if we redefine finalize method
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
- */
-
-/*
- * Regression test for hitting:
- *
- * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
- *
- * when redefining finalizer method
- */
-
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineFinalizer_B {
- protected void finalize() {
- // should be empty
- }
-}
-
-public class RedefineFinalizer {
-
- public static String newB =
- "class RedefineFinalizer_B {" +
- " protected void finalize() { " +
- " System.out.println(\"Finalizer called\");" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
-
- A a = new A();
- }
-
- static class A extends RedefineFinalizer_B {
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceCall.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2017, 2018, 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
- * @bug 8174962 8010319
- * @summary Redefine class with interface method call
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
- */
-
-import static jdk.test.lib.Asserts.assertEquals;
-
-interface I1 { default int m() { return 0; } }
-interface I2 extends I1 {}
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineInterfaceCall_C implements I2 {
- public int test(I2 i) {
- return i.m(); // invokeinterface cpCacheEntry
- }
-}
-
-public class RedefineInterfaceCall {
-
- static String newI1 =
- "interface I1 { default int m() { return 1; } }";
-
- static String newC =
- "class RedefineInterfaceCall_C implements I2 { " +
- " public int test(I2 i) { " +
- " return i.m(); " +
- " } " +
- "} ";
-
- static int test(I2 i) {
- return i.m(); // invokeinterface cpCacheEntry
- }
-
- public static void main(String[] args) throws Exception {
- RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
-
- assertEquals(test(c), 0);
- assertEquals(c.test(c), 0);
-
- RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
-
- assertEquals(c.test(c), 0);
-
- RedefineClassHelper.redefineClass(I1.class, newI1);
-
- assertEquals(test(c), 1);
- assertEquals(c.test(c), 1);
-
- RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
-
- assertEquals(c.test(c), 1);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineInterfaceMethods.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, 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
- * @bug 8081800 8010319
- * @summary Redefine private and default interface methods
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
- */
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-interface RedefineInterfaceMethods_B {
- int ORIGINAL_RETURN = 1;
- int NEW_RETURN = 2;
- private int privateMethod() {
- return ORIGINAL_RETURN;
- }
- public default int defaultMethod() {
- return privateMethod();
- }
-}
-
-public class RedefineInterfaceMethods {
-
- static final int RET = -2;
-
- public static String redefinedPrivateMethod =
- "interface RedefineInterfaceMethods_B {" +
- " int ORIGINAL_RETURN = 1;" +
- " int NEW_RETURN = 2;" +
- " private int privateMethod() {" +
- " return NEW_RETURN;" +
- " }" +
- " public default int defaultMethod() {" +
- " return privateMethod();" +
- " }" +
- "}";
-
- public static String redefinedDefaultMethod =
- "interface RedefineInterfaceMethods_B {" +
- " int ORIGINAL_RETURN = 1;" +
- " int NEW_RETURN = 2;" +
- " private int privateMethod() {" +
- " return ORIGINAL_RETURN;" +
- " }" +
- " public default int defaultMethod() {" +
- " return RedefineInterfaceMethods.RET;" +
- " }" +
- "}";
-
- static class Impl implements RedefineInterfaceMethods_B {
- }
-
-
- public static void main(String[] args) throws Exception {
-
- Impl impl = new Impl();
-
- int res = impl.defaultMethod();
- if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
- throw new Error("defaultMethod returned " + res +
- " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
-
- RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
-
- res = impl.defaultMethod();
- if (res != RedefineInterfaceMethods_B.NEW_RETURN)
- throw new Error("defaultMethod returned " + res +
- " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
-
- System.gc();
-
- RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
-
- res = impl.defaultMethod();
- if (res != RET)
- throw new Error("defaultMethod returned " + res +
- " expected " + RET);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineLeak.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,112 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * 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
- * @library /test/lib
- * @summary Test that redefinition reuses metaspace blocks that are freed
- * @modules java.base/jdk.internal.misc
- * @modules java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineLeak buildagent
- * @run main/othervm/timeout=6000 RedefineLeak runtest
- */
-
-import java.io.FileNotFoundException;
-import java.io.PrintWriter;
-import java.lang.RuntimeException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
-import java.lang.instrument.IllegalClassFormatException;
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-public class RedefineLeak {
- static class Tester {}
-
- static class LoggingTransformer implements ClassFileTransformer {
- static int transformCount = 0;
-
- public LoggingTransformer() {}
-
- public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
-
- transformCount++;
- if (transformCount % 1000 == 0) System.out.println("transformCount:" + transformCount);
- return null;
- }
- }
-
- public static void premain(String agentArgs, Instrumentation inst) throws Exception {
- LoggingTransformer t = new LoggingTransformer();
- inst.addTransformer(t, true);
- {
- Class demoClass = Class.forName("RedefineLeak$Tester");
-
- for (int i = 0; i < 10000; i++) {
- inst.retransformClasses(demoClass);
- }
- }
- System.gc();
- }
- private static void buildAgent() {
- try {
- ClassFileInstaller.main("RedefineLeak");
- } catch (Exception e) {
- throw new RuntimeException("Could not write agent classfile", e);
- }
-
- try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
- pw.println("Premain-Class: RedefineLeak");
- pw.println("Agent-Class: RedefineLeak");
- pw.println("Can-Redefine-Classes: true");
- pw.println("Can-Retransform-Classes: true");
- pw.close();
- } catch (FileNotFoundException e) {
- throw new RuntimeException("Could not write manifest file for the agent", e);
- }
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineLeak.class" })) {
- throw new RuntimeException("Could not write the agent jar file");
- }
- }
- public static void main(String argv[]) throws Exception {
- if (argv.length == 1 && argv[0].equals("buildagent")) {
- buildAgent();
- return;
- }
- if (argv.length == 1 && argv[0].equals("runtest")) {
- // run outside of jtreg to not OOM on jtreg classes that are loaded after metaspace is full
- String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
- "-javaagent:redefineagent.jar", "RedefineLeak"};
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
-
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("transformCount:10000");
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefinePreviousVersions.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) 2016, 2018, 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
- * @bug 8165246 8010319
- * @summary Test has_previous_versions flag and processing during class unloading.
- * @requires vm.opt.final.ClassUnloading
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm RedefinePreviousVersions test
- */
-
-import jdk.test.lib.process.ProcessTools;
-import jdk.test.lib.process.OutputAnalyzer;
-
-// package access top-level classes to avoid problem with RedefineClassHelper
-// and nested types.
-
-class RedefinePreviousVersions_B { }
-
-class RedefinePreviousVersions_Running {
- public static volatile boolean stop = false;
- public static volatile boolean running = false;
- static void localSleep() {
- try {
- Thread.sleep(10); // sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- running = true;
- while (!stop) { localSleep(); }
- }
-}
-
-
-
-public class RedefinePreviousVersions {
-
- public static String newB =
- "class RedefinePreviousVersions_B {" +
- "}";
-
- public static String newRunning =
- "class RedefinePreviousVersions_Running {" +
- " public static volatile boolean stop = true;" +
- " public static volatile boolean running = true;" +
- " static void localSleep() { }" +
- " public static void infinite() { }" +
- "}";
-
- public static void main(String[] args) throws Exception {
-
- if (args.length > 0) {
-
- // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
- "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
- "RedefinePreviousVersions");
- new OutputAnalyzer(pb.start())
- .shouldContain("Class unloading: has_previous_versions = false")
- .shouldContain("Class unloading: has_previous_versions = true")
- .shouldHaveExitValue(0);
- return;
- }
-
- // Redefine a class and create some garbage
- // Since there are no methods running, the previous version is never added to the
- // previous_version_list and the flag _has_previous_versions should stay false
- RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
-
- for (int i = 0; i < 10 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- // Start a class that has a method running
- new Thread() {
- public void run() {
- RedefinePreviousVersions_Running.infinite();
- }
- }.start();
-
- while (!RedefinePreviousVersions_Running.running) {
- Thread.sleep(10); // sleep for 10 ms
- }
-
- // Since a method of newRunning is running, this class should be added to the previous_version_list
- // of Running, and _has_previous_versions should return true at class unloading.
- RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
-
- for (int i = 0; i < 10 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- // purge should clean everything up, except Xcomp it might not.
- RedefinePreviousVersions_Running.stop = true;
-
- for (int i = 0; i < 10 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethods.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,150 +0,0 @@
-/*
- * Copyright (c) 2014, 2018, 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
- * @bug 8055008 8197901 8010319
- * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log RedefineRunningMethods
- */
-
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-class RedefineRunningMethods_B {
- static int count1 = 0;
- static int count2 = 0;
- public static volatile boolean stop = false;
- static void localSleep() {
- try{
- Thread.currentThread().sleep(10);//sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- while (!stop) { count1++; localSleep(); }
- }
- public static void infinite_emcp() {
- while (!stop) { count2++; localSleep(); }
- }
-}
-
-public class RedefineRunningMethods {
-
- public static String newB =
- "class RedefineRunningMethods_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.currentThread().sleep(10);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { " +
- " System.out.println(\"infinite called\");" +
- " }" +
- " public static void infinite_emcp() { " +
- " while (!stop) { count2++; localSleep(); }" +
- " }" +
- "}";
-
- public static String evenNewerB =
- "class RedefineRunningMethods_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.currentThread().sleep(1);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { }" +
- " public static void infinite_emcp() { " +
- " System.out.println(\"infinite_emcp now obsolete called\");" +
- " }" +
- "}";
-
-
- public static void main(String[] args) throws Exception {
-
- new Thread() {
- public void run() {
- RedefineRunningMethods_B.infinite();
- }
- }.start();
-
- new Thread() {
- public void run() {
- RedefineRunningMethods_B.infinite_emcp();
- }
- }.start();
-
- RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
-
- System.gc();
-
- RedefineRunningMethods_B.infinite();
-
- // Start a thread with the second version of infinite_emcp running
- new Thread() {
- public void run() {
- RedefineRunningMethods_B.infinite_emcp();
- }
- }.start();
-
- for (int i = 0; i < 20 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
- System.gc();
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethods_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
-
- RedefineRunningMethods_B.infinite_emcp();
-
- // purge should clean everything up.
- RedefineRunningMethods_B.stop = true;
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethods_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-/*
- * Copyright (c) 2015, 2018, 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
- * @bug 8087315 8010319
- * @summary Get old method's stack trace elements after GC
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
- */
-
-import static jdk.test.lib.Asserts.*;
-
-// package access top-level class to avoid problem with RedefineClassHelper
-// and nested types.
-
-class RedefineRunningMethodsWithBacktrace_B {
- static int count1 = 0;
- static int count2 = 0;
- public static volatile boolean stop = false;
- static void localSleep() {
- try {
- Thread.sleep(10);//sleep for 10 ms
- } catch(InterruptedException ie) {
- }
- }
-
- public static void infinite() {
- while (!stop) { count1++; localSleep(); }
- }
- public static void throwable() {
- // add some stuff to the original constant pool
- String s1 = new String ("string1");
- String s2 = new String ("string2");
- String s3 = new String ("string3");
- String s4 = new String ("string4");
- String s5 = new String ("string5");
- String s6 = new String ("string6");
- String s7 = new String ("string7");
- String s8 = new String ("string8");
- String s9 = new String ("string9");
- String s10 = new String ("string10");
- String s11 = new String ("string11");
- String s12 = new String ("string12");
- String s13 = new String ("string13");
- String s14 = new String ("string14");
- String s15 = new String ("string15");
- String s16 = new String ("string16");
- String s17 = new String ("string17");
- String s18 = new String ("string18");
- String s19 = new String ("string19");
- throw new RuntimeException("throwable called");
- }
-}
-
-public class RedefineRunningMethodsWithBacktrace {
-
- public static String newB =
- "class RedefineRunningMethodsWithBacktrace_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.sleep(10);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { " +
- " System.out.println(\"infinite called\");" +
- " }" +
- " public static void throwable() { " +
- " throw new RuntimeException(\"throwable called\");" +
- " }" +
- "}";
-
- public static String evenNewerB =
- "class RedefineRunningMethodsWithBacktrace_B {" +
- " static int count1 = 0;" +
- " static int count2 = 0;" +
- " public static volatile boolean stop = false;" +
- " static void localSleep() { " +
- " try{ " +
- " Thread.sleep(1);" +
- " } catch(InterruptedException ie) { " +
- " } " +
- " } " +
- " public static void infinite() { }" +
- " public static void throwable() { " +
- " throw new RuntimeException(\"throwable called\");" +
- " }" +
- "}";
-
- private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
- System.out.println("touchRedefinedMethodInBacktrace: ");
- throwable.printStackTrace(); // this actually crashes with the bug in
- // java_lang_StackTraceElement::create()
-
- // Make sure that we can convert the backtrace, which is referring to
- // the redefined method, to a StrackTraceElement[] without crashing.
- StackTraceElement[] stackTrace = throwable.getStackTrace();
- for (int i = 0; i < stackTrace.length; i++) {
- StackTraceElement frame = stackTrace[i];
- assertNotNull(frame.getClassName(),
- "\nTest failed: trace[" + i + "].getClassName() returned null");
- assertNotNull(frame.getMethodName(),
- "\nTest failed: trace[" + i + "].getMethodName() returned null");
- }
- }
-
- private static Throwable getThrowableInB() {
- Throwable t = null;
- try {
- RedefineRunningMethodsWithBacktrace_B.throwable();
- } catch (Exception e) {
- t = e;
- // Don't print here because Throwable will cache the constructed stacktrace
- // e.printStackTrace();
- }
- return t;
- }
-
-
- public static void main(String[] args) throws Exception {
-
- new Thread() {
- public void run() {
- RedefineRunningMethodsWithBacktrace_B.infinite();
- }
- }.start();
-
- Throwable t1 = getThrowableInB();
-
- RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
-
- System.gc();
-
- Throwable t2 = getThrowableInB();
-
- RedefineRunningMethodsWithBacktrace_B.infinite();
-
- for (int i = 0; i < 20 ; i++) {
- String s = new String("some garbage");
- System.gc();
- }
-
- RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
- System.gc();
-
- Throwable t3 = getThrowableInB();
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethodsWithBacktrace_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
-
- touchRedefinedMethodInBacktrace(t1);
- touchRedefinedMethodInBacktrace(t2);
- touchRedefinedMethodInBacktrace(t3);
-
- // purge should clean everything up.
- RedefineRunningMethodsWithBacktrace_B.stop = true;
-
- for (int i = 0; i < 20 ; i++) {
- RedefineRunningMethodsWithBacktrace_B.infinite();
- String s = new String("some garbage");
- System.gc();
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-/*
- * Copyright (c) 2014, 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.
- *
- * 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
- * @bug 8076110
- * @summary Redefine running methods that have cached resolution errors
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.base/jdk.internal.org.objectweb.asm
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethodsWithResolutionErrors
- */
-
-import jdk.internal.org.objectweb.asm.ClassWriter;
-import jdk.internal.org.objectweb.asm.Label;
-import jdk.internal.org.objectweb.asm.MethodVisitor;
-import jdk.internal.org.objectweb.asm.Opcodes;
-
-import java.lang.reflect.InvocationTargetException;
-
-public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- if (name.equals("C")) {
- byte[] b = loadC(false);
- return defineClass(name, b, 0, b.length);
- } else {
- return super.findClass(name);
- }
- }
-
- private static byte[] loadC(boolean redefine) {
- ClassWriter cw = new ClassWriter(0);
-
- cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
- {
- MethodVisitor mv;
-
- mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
- mv.visitCode();
-
- // First time we run we will:
- // 1) Cache resolution errors
- // 2) Redefine the class / method
- // 3) Try to read the resolution errors that were cached
- //
- // The redefined method will never run, throw error to be sure
- if (redefine) {
- createThrowRuntimeExceptionCode(mv, "The redefined method was called");
- } else {
- createMethodBody(mv);
- }
- mv.visitMaxs(3, 0);
- mv.visitEnd();
- }
- cw.visitEnd();
- return cw.toByteArray();
- }
-
- private static void createMethodBody(MethodVisitor mv) {
- Label classExists = new Label();
-
- // Cache resolution errors
- createLoadNonExistentClassCode(mv, classExists);
-
- // Redefine our own class and method
- mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
-
- // Provoke the same error again to make sure the resolution error cache works
- createLoadNonExistentClassCode(mv, classExists);
-
- // Test passed
- mv.visitInsn(RETURN);
-
- mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
- mv.visitLabel(classExists);
-
- createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
- }
-
- private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
- Label tryLoadBegin = new Label();
- Label tryLoadEnd = new Label();
- Label catchLoadBlock = new Label();
- mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
-
- // Try to load a class that does not exist to provoke resolution errors
- mv.visitLabel(tryLoadBegin);
- mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
- mv.visitLabel(tryLoadEnd);
-
- // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
- mv.visitJumpInsn(GOTO, classExists);
-
- mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
- mv.visitLabel(catchLoadBlock);
-
- // Ignore the expected NoClassDefFoundError
- mv.visitInsn(POP);
- }
-
- private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
- mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
- mv.visitInsn(DUP);
- mv.visitLdcInsn(msg);
- mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
- mv.visitInsn(ATHROW);
- }
-
- private static Class<?> c;
-
- public static void redefine() throws Exception {
- RedefineClassHelper.redefineClass(c, loadC(true));
- }
-
- public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
- c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
- c.getMethod("m").invoke(null);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/RedefineSubtractLambdaExpression.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
- * Copyright (c) 2018, 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
- * @bug 8193524
- * @summary Redefine a class' public static method that contains a lambda expression
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression
- */
-
-interface MathOperation {
- public int operation(int a, int b);
-}
-
-class B {
- public static int operate(int a, int b, MathOperation mathOperation) {
- return mathOperation.operation(a, b);
- }
- static int test_math(String p) {
- System.out.println(p + " from class B's test_math method");
- MathOperation subtraction = (int a, int b) -> a - b;
- MathOperation addition = (int a, int b) -> a + b;
- return operate(10, 5, addition);
- }
-}
-
-public class RedefineSubtractLambdaExpression {
-
- public static String newB =
- "class B {" +
- " public static int operate(int a, int b, MathOperation mathOperation) {" +
- " return mathOperation.operation(a, b);" +
- " }" +
- " static int test_math(String p) {" +
- " MathOperation subtraction = (int a, int b) -> a - b;" +
- " return operate(10, 5, subtraction);" +
- " }" +
- "}";
-
- public static void main(String[] args) throws Exception {
- int res = B.test_math("Hello");
- System.out.println("Result = " + res);
- if (res != 15) {
- throw new Error("test_math returned " + res + " expected " + 15);
- }
- RedefineClassHelper.redefineClass(B.class, newB);
-
- res = B.test_math("Hello");
- if (res != 5)
- throw new Error("test_math returned " + res + " expected " + 5);
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/TestMultipleClasses.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * 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.
- */
-
-/*
- * @test
- * @bug 8139551
- * @summary Scalability problem with redefinition - multiple code cache walks
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * @modules java.compiler
- * java.instrument
- * jdk.jartool/sun.tools.jar
- * @run main RedefineClassHelper
- * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -XX:CompileThreshold=100 -Xlog:redefine+class+nmethod=debug TestMultipleClasses
- */
-
-import java.lang.instrument.*;
-import java.lang.reflect.*;
-import jdk.test.lib.compiler.InMemoryJavaCompiler;
-
-public class TestMultipleClasses extends ClassLoader {
-
- public static String B(int count) {
- return new String("public class B" + count + " {" +
- " public static void compiledMethod() { " +
- " try{" +
- " Thread.sleep(1); " +
- " } catch(InterruptedException ie) {" +
- " }" +
- " }" +
- "}");
- }
-
- static String newB(int count) {
- return new String("public class B" + count + " {" +
- " public static void compiledMethod() { " +
- " System.out.println(\"compiledMethod called " + count + "\");" +
- " }" +
- "}");
- }
-
- static int index = 0;
-
- @Override
- protected Class<?> findClass(String name) throws ClassNotFoundException {
- if (name.equals("B" + index)) {
- byte[] b = InMemoryJavaCompiler.compile(name, B(index));
- return defineClass(name, b, 0, b.length);
- } else {
- return super.findClass(name);
- }
- }
-
- 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);
- }
- }
-
- public static void main(String[] args) throws Exception {
-
- final int numberOfClasses = 20;
- Class[] classes = new Class[numberOfClasses];
- byte[][] newClass = new byte[numberOfClasses][];
- ClassDefinition[] defs = new ClassDefinition[numberOfClasses];
-
- TestMultipleClasses loader = new TestMultipleClasses();
-
- // Load and start all the classes.
- for (index = 0; index < numberOfClasses; index++) {
- String name = new String("B" + index);
- Class c = loader.findClass(name);
-
- runCompiledMethodMethods(c, 500);
- // Make class definition for redefinition
- classes[index] = c;
- newClass[index] = InMemoryJavaCompiler.compile(c.getName(), newB(index));
- defs[index] = new ClassDefinition(c, newClass[index]);
- }
-
- long startTime = System.currentTimeMillis();
-
- // Redefine all classes.
- RedefineClassHelper.instrumentation.redefineClasses(defs);
-
- long endTime = System.currentTimeMillis();
-
- System.out.println("Redefinition took " + (endTime - startTime) + " milliseconds");
-
- System.gc();
-
- // Run all new classes.
- for (index = 0; index < numberOfClasses; index++) {
- runCompiledMethodMethods(classes[index], 1);
- }
- }
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/libRedefineDeleteJmethod.c Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-#include <jni.h>
-
-jmethodID mid;
-jclass cls;
-static int count = 0;
-
-JNIEXPORT jint JNICALL
-Java_RedefineDeleteJmethod_jniCallDeleteMe(JNIEnv* env, jobject obj) {
-
- if (count == 0) {
- count++;
- cls = (*env)->FindClass(env, "B");
- if (NULL == cls) {
- (*env)->FatalError(env, "could not find class");
- }
-
- mid = (*env)->GetStaticMethodID(env, cls, "deleteMe", "()I");
- if (NULL == mid) {
- (*env)->FatalError(env, "could not find method");
- }
- }
-
- return (*env)->CallStaticIntMethod(env, cls, mid);
-}
--- a/test/hotspot/jtreg/runtime/RedefineTests/libRedefineDoubleDelete.c Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,164 +0,0 @@
-/*
- * Copyright (c) 2017, 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.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include "jvmti.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef JNI_ENV_ARG
-
-#ifdef __cplusplus
-#define JNI_ENV_ARG(x, y) y
-#define JNI_ENV_PTR(x) x
-#else
-#define JNI_ENV_ARG(x,y) x, y
-#define JNI_ENV_PTR(x) (*x)
-#endif
-
-#endif
-
-#define TranslateError(err) "JVMTI error"
-
-static jvmtiEnv *jvmti = NULL;
-
-static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
-
-JNIEXPORT
-jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
- return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
- return Agent_Initialize(jvm, options, reserved);
-}
-
-JNIEXPORT
-jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
- return JNI_VERSION_9;
-}
-
-
-static jint newClassDataLen = 0;
-static unsigned char* newClassData = NULL;
-
-static jint
-getBytecodes(jvmtiEnv *jvmti_env,
- jint class_data_len, const unsigned char* class_data) {
- int i;
- jint res;
-
- newClassDataLen = class_data_len;
- res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
- if (res != JNI_OK) {
- printf(" Unable to allocate bytes\n");
- return JNI_ERR;
- }
- for (i = 0; i < newClassDataLen; i++) {
- newClassData[i] = class_data[i];
- // Rewrite oo in class to aa
- if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
- newClassData[i] = newClassData[i-1] = 'a';
- }
- }
- printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
- return JNI_OK;
-}
-
-
-static void JNICALL
-Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
- jclass class_being_redefined,
- jobject loader, const char* name, jobject protection_domain,
- jint class_data_len, const unsigned char* class_data,
- jint *new_class_data_len, unsigned char** new_class_data) {
- if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
- if (newClassData == NULL) {
- jint res = getBytecodes(jvmti_env, class_data_len, class_data);
- if (res == JNI_ERR) {
- printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
- return;
- }
- // Only change for first CFLH event.
- *new_class_data_len = newClassDataLen;
- *new_class_data = newClassData;
- }
- printf(">>> ClassFileLoadHook event: class name %s\n", name);
- }
-}
-
-static
-jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
- jint res, size;
- jvmtiCapabilities caps;
- jvmtiEventCallbacks callbacks;
- jvmtiError err;
-
- res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
- JVMTI_VERSION_9);
- if (res != JNI_OK || jvmti == NULL) {
- printf(" Error: wrong result of a valid call to GetEnv!\n");
- return JNI_ERR;
- }
-
- printf("Enabling following capabilities: can_generate_all_class_hook_events, "
- "can_retransform_classes, can_redefine_classes");
- memset(&caps, 0, sizeof(caps));
- caps.can_generate_all_class_hook_events = 1;
- caps.can_retransform_classes = 1;
- caps.can_redefine_classes = 1;
- printf("\n");
-
- err = (*jvmti)->AddCapabilities(jvmti, &caps);
- if (err != JVMTI_ERROR_NONE) {
- printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
- return JNI_ERR;
- }
-
- size = (jint)sizeof(callbacks);
-
- memset(&callbacks, 0, sizeof(callbacks));
- callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
-
- err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
- if (err != JVMTI_ERROR_NONE) {
- printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
- return JNI_ERR;
- }
-
- err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
- if (err != JVMTI_ERROR_NONE) {
- printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
- return JNI_ERR;
- }
-
- return JNI_OK;
-}
-
-#ifdef __cplusplus
-}
-#endif
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java Tue Mar 19 14:32:41 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineBasicTest.java Tue Mar 19 14:22:47 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -24,10 +24,10 @@
/*
* @test
- * @summary Run /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to
+ * @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
* make sure class redefinition works with CDS.
* @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds
+ * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/appcds
* @modules java.compiler
* java.instrument
* jdk.jartool/sun.tools.jar
--- a/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java Tue Mar 19 14:32:41 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/redefineClass/RedefineRunningMethods_Shared.java Tue Mar 19 14:22:47 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -24,10 +24,10 @@
/*
* @test
- * @summary Run /runtime/RedefineTests/RedefineRunningMethods in AppCDS mode to
+ * @summary Run /serviceability/jvmti/RedefineClasses/RedefineRunningMethods in AppCDS mode to
* make sure class redefinition works with CDS.
* @requires vm.cds
- * @library /test/lib /test/hotspot/jtreg/runtime/RedefineTests /test/hotspot/jtreg/runtime/appcds
+ * @library /test/lib /test/hotspot/jtreg/serviceability/jvmti/RedefineClasses /test/hotspot/jtreg/runtime/appcds
* @modules java.base/jdk.internal.misc
* @modules java.compiler
* java.instrument
--- a/test/hotspot/jtreg/runtime/logging/RedefineClasses.java Tue Mar 19 14:32:41 2019 -0400
+++ b/test/hotspot/jtreg/runtime/logging/RedefineClasses.java Tue Mar 19 14:22:47 2019 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -25,7 +25,7 @@
* @test
* @bug 8197901 8209758
* @summary Redefine classes with enabling logging to verify Klass:external_name() during GC.
- * @comment This test is simplified version of runtime/RedefineTests/RedefineRunningMethods.java.
+ * @comment This test is simplified version of serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java.
* @library /test/lib
* @modules java.compiler
* java.instrument
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/Agent.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+import java.security.*;
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+
+public class Agent implements ClassFileTransformer {
+ public synchronized byte[] transform(final ClassLoader classLoader,
+ final String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer) {
+ System.out.println("Transforming class " + className);
+ return classfileBuffer;
+ }
+
+ public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
+
+ try {
+ instrumentation.retransformClasses(to_redefine);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+ public static void premain(String agentArgs, Instrumentation instrumentation) {
+ Agent transformer = new Agent();
+ instrumentation.addTransformer(transformer, true);
+
+ // Redefine java/lang/Object and java/lang/reflect/Method.invoke and
+ // java/lang/ClassLoader
+ Class object_class = Object.class;
+ redefine(agentArgs, instrumentation, object_class);
+
+ Class method_class = Method.class;
+ redefine(agentArgs, instrumentation, method_class);
+
+ Class loader_class = ClassLoader.class;
+ redefine(agentArgs, instrumentation, loader_class);
+
+ instrumentation.removeTransformer(transformer);
+ }
+
+ public static void main(String[] args) {
+ byte[] ba = new byte[0];
+
+ // If it survives 100 GC's, it's good.
+ for (int i = 0; i < 100 ; i++) {
+ System.gc();
+ ba.clone();
+ }
+ try {
+ // Use java/lang/reflect/Method.invoke to call
+ WalkThroughInvoke a = new WalkThroughInvoke();
+ Class aclass = WalkThroughInvoke.class;
+ Method m = aclass.getMethod("stackWalk");
+ m.invoke(a);
+ } catch (Exception x) {
+ x.printStackTrace();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/ModifyAnonymous.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @summary Test that retransforming and redefining anonymous classes gets UnmodifiableClassException
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main ModifyAnonymous buildagent
+ * @run main/othervm -javaagent:redefineagent.jar ModifyAnonymous
+ */
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class ModifyAnonymous {
+
+ public static class LambdaTransformer implements ClassFileTransformer {
+ @Override
+ public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+ return null;
+ }
+ }
+
+ static Instrumentation inst = null;
+ static volatile boolean done = false;
+
+ public static void premain(String args, Instrumentation instrumentation) {
+
+ inst = instrumentation;
+ System.out.println("javaagent in da house!");
+ instrumentation.addTransformer(new LambdaTransformer());
+ }
+
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("ModifyAnonymous");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: ModifyAnonymous");
+ pw.println("Agent-Class: ModifyAnonymous");
+ pw.println("Can-Retransform-Classes: true");
+ pw.println("Can-Redefine-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "ModifyAnonymous.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+
+ public static class InstanceMethodCallSiteApp {
+
+ public static void test() throws InterruptedException {
+ for (int i = 0; i < 2; i++) {
+ InstanceMethodCallSiteApp app = new InstanceMethodCallSiteApp();
+ Runnable r = app::doWork; // this creates an anonymous class
+ while (!done) {
+ r.run();
+ Thread.sleep(10);
+ }
+ }
+ }
+
+ public void doWork() {
+ System.out.print(".");
+ }
+ }
+
+ static void runTest() {
+ PrintWriter pw;
+ String logName = System.getProperty("test.classes") +
+ File.separator + "loadedClasses.log";
+ // Create a log file to capture the names of the classes in the
+ // allLoadedClasses array. The log file is for assisting in debugging
+ // in case a null class is encountered in the allLoadedClasses array.
+ try {
+ pw = new PrintWriter(new FileOutputStream(
+ new File(logName), true));
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write loaded classes to log", e);
+ }
+ while (!done) {
+ Class[] allLoadedClasses = inst.getAllLoadedClasses();
+ int len = allLoadedClasses.length;
+ pw.println(" allLoadedClasses length: " + len);
+ for (int idx = 0; idx < len; idx++) {
+ Class cls = allLoadedClasses[idx];
+ pw.println(" " + idx + " " +
+ ((cls != null) ? cls.getName() : "null"));
+ }
+ for (int idx = 0; idx < len; idx++) {
+ Class clazz = allLoadedClasses[idx];
+ if (clazz == null) {
+ pw.flush();
+ pw.close();
+ throw new RuntimeException("null class encountered");
+ }
+ final String name = clazz.getName();
+ if (name.contains("$$Lambda$") && name.contains("App")) {
+ if (inst.isModifiableClass(clazz)) {
+ pw.flush();
+ pw.close();
+ throw new RuntimeException ("Class should not be modifiable");
+ }
+ // Try to modify them anyway.
+ try {
+ System.out.println("retransform called for " + name);
+ inst.retransformClasses(clazz);
+ } catch(java.lang.instrument.UnmodifiableClassException t) {
+ System.out.println("PASSED: expecting UnmodifiableClassException");
+ t.printStackTrace();
+ }
+ try {
+ System.out.println("redefine called for " + name);
+ String newclass = "class Dummy {}";
+ byte[] bytecode = InMemoryJavaCompiler.compile("Dummy", newclass);
+ ClassDefinition cld = new ClassDefinition(clazz, bytecode);
+ inst.redefineClasses(new ClassDefinition[] { cld });
+ } catch(java.lang.instrument.UnmodifiableClassException t) {
+ System.out.println("PASSED: expecting UnmodifiableClassException");
+ t.printStackTrace();
+ } catch(java.lang.ClassNotFoundException e) {
+ pw.flush();
+ pw.close();
+ throw new RuntimeException ("ClassNotFoundException thrown");
+ }
+ done = true;
+ }
+ }
+ }
+ pw.flush();
+ pw.close();
+ }
+
+ public static void main(String argv[]) throws InterruptedException, RuntimeException {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+
+ if (inst == null) {
+ throw new RuntimeException("Instrumentation object was null");
+ }
+
+ new Thread() {
+ public void run() {
+ runTest();
+ }
+ }.start();
+
+ // Test that NCDFE is not thrown for anonymous class:
+ // ModifyAnonymous$InstanceMethodCallSiteApp$$Lambda$18
+ try {
+ ModifyAnonymous test = new ModifyAnonymous();
+ InstanceMethodCallSiteApp.test();
+ } catch (NoClassDefFoundError e) {
+ throw new RuntimeException("FAILED: NoClassDefFoundError thrown for " + e.getMessage());
+ }
+ System.out.println("PASSED: NoClassDefFound error not thrown");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAddLambdaExpression.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8193524
+ * @summary Redefine a class' public static method that contains a lambda expression
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineAddLambdaExpression
+ */
+
+interface MathOperation {
+ public int operation(int a, int b);
+}
+
+class B {
+ public static int operate(int a, int b, MathOperation mathOperation) {
+ return mathOperation.operation(a, b);
+ }
+ static int test_math(String p) {
+ MathOperation addition = (int a, int b) -> a + b;
+ return operate(10, 5, addition);
+ }
+}
+
+public class RedefineAddLambdaExpression {
+
+ public static String newB =
+ "class B {" +
+ " public static int operate(int a, int b, MathOperation mathOperation) {" +
+ " return mathOperation.operation(a, b);" +
+ " }" +
+ " static int test_math(String p) {" +
+ " MathOperation addition = (int a, int b) -> a + b;" +
+ " System.out.println(p + \" from class B's test_math method\");" +
+ " MathOperation subtraction = (int a, int b) -> a - b;" +
+ " return operate(10, 5, subtraction);" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ int res = B.test_math("Hello");
+ System.out.println("Result = " + res);
+ if (res != 15) {
+ throw new Error("test_math returned " + res + " expected " + 15);
+ }
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ res = B.test_math("Hello");
+ if (res != 5)
+ throw new Error("test_math returned " + res + " expected " + 5);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,414 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @summary Test that type annotations are retained after a retransform
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineAnnotations buildagent
+ * @run main/othervm -javaagent:redefineagent.jar RedefineAnnotations
+ */
+
+import static jdk.test.lib.Asserts.assertTrue;
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.NoSuchFieldException;
+import java.lang.NoSuchMethodException;
+import java.lang.RuntimeException;
+import java.lang.annotation.Annotation;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.lang.reflect.AnnotatedArrayType;
+import java.lang.reflect.AnnotatedParameterizedType;
+import java.lang.reflect.AnnotatedType;
+import java.lang.reflect.AnnotatedWildcardType;
+import java.lang.reflect.Executable;
+import java.lang.reflect.TypeVariable;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+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.FieldVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.ASM7;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE_USE)
+@interface TestAnn {
+ String site();
+}
+
+public class RedefineAnnotations {
+ static Instrumentation inst;
+ public static void premain(String agentArgs, Instrumentation inst) {
+ RedefineAnnotations.inst = inst;
+ }
+
+ static class Transformer implements ClassFileTransformer {
+
+ public byte[] asm(ClassLoader loader, String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+
+ ClassWriter cw = new ClassWriter(0);
+ ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { };
+ ClassReader cr = new ClassReader(classfileBuffer);
+ cr.accept(cv, 0);
+ return cw.toByteArray();
+ }
+
+ public class ReAddDummyFieldsClassVisitor extends ClassVisitor {
+
+ LinkedList<F> fields = new LinkedList<>();
+
+ public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) {
+ super(api, cv);
+ }
+
+ @Override public FieldVisitor visitField(int access, String name,
+ String desc, String signature, Object value) {
+ if (name.startsWith("dummy")) {
+ // Remove dummy field
+ fields.addLast(new F(access, name, desc, signature, value));
+ return null;
+ }
+ return cv.visitField(access, name, desc, signature, value);
+ }
+
+ @Override public void visitEnd() {
+ F f;
+ while ((f = fields.pollFirst()) != null) {
+ // Re-add dummy fields
+ cv.visitField(f.access, f.name, f.desc, f.signature, f.value);
+ }
+ }
+
+ private class F {
+ private int access;
+ private String name;
+ private String desc;
+ private String signature;
+ private Object value;
+ F(int access, String name, String desc, String signature, Object value) {
+ this.access = access;
+ this.name = name;
+ this.desc = desc;
+ this.signature = signature;
+ this.value = value;
+ }
+ }
+ }
+
+ @Override public byte[] transform(ClassLoader loader, String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer)
+ throws IllegalClassFormatException {
+
+ if (className.contains("TypeAnnotatedTestClass")) {
+ try {
+ // Here we remove and re-add the dummy fields. This shuffles the constant pool
+ return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
+ } catch (Throwable e) {
+ // The retransform native code that called this method does not propagate
+ // exceptions. Instead of getting an uninformative generic error, catch
+ // problems here and print it, then exit.
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+ return null;
+ }
+ }
+
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("RedefineAnnotations");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: RedefineAnnotations");
+ pw.println("Agent-Class: RedefineAnnotations");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineAnnotations.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+
+ public static void main(String argv[]) throws NoSuchFieldException, NoSuchMethodException {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+
+ if (inst == null) {
+ throw new RuntimeException("Instrumentation object was null");
+ }
+
+ RedefineAnnotations test = new RedefineAnnotations();
+ test.testTransformAndVerify();
+ }
+
+ // Class type annotations
+ private Annotation classTypeParameterTA;
+ private Annotation extendsTA;
+ private Annotation implementsTA;
+
+ // Field type annotations
+ private Annotation fieldTA;
+ private Annotation innerTA;
+ private Annotation[] arrayTA = new Annotation[4];
+ private Annotation[] mapTA = new Annotation[5];
+
+ // Method type annotations
+ private Annotation returnTA, methodTypeParameterTA, formalParameterTA, throwsTA;
+
+ private void testTransformAndVerify()
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Class<TypeAnnotatedTestClass> c = TypeAnnotatedTestClass.class;
+ Class<?> myClass = c;
+
+ /*
+ * Verify that the expected annotations are where they should be before transform.
+ */
+ verifyClassTypeAnnotations(c);
+ verifyFieldTypeAnnotations(c);
+ verifyMethodTypeAnnotations(c);
+
+ try {
+ inst.addTransformer(new Transformer(), true);
+ inst.retransformClasses(myClass);
+ } catch (UnmodifiableClassException e) {
+ throw new RuntimeException(e);
+ }
+
+ /*
+ * Verify that the expected annotations are where they should be after transform.
+ * Also verify that before and after are equal.
+ */
+ verifyClassTypeAnnotations(c);
+ verifyFieldTypeAnnotations(c);
+ verifyMethodTypeAnnotations(c);
+ }
+
+ private void verifyClassTypeAnnotations(Class c) {
+ Annotation anno;
+
+ anno = c.getTypeParameters()[0].getAnnotations()[0];
+ verifyTestAnn(classTypeParameterTA, anno, "classTypeParameter");
+ classTypeParameterTA = anno;
+
+ anno = c.getAnnotatedSuperclass().getAnnotations()[0];
+ verifyTestAnn(extendsTA, anno, "extends");
+ extendsTA = anno;
+
+ anno = c.getAnnotatedInterfaces()[0].getAnnotations()[0];
+ verifyTestAnn(implementsTA, anno, "implements");
+ implementsTA = anno;
+ }
+
+ private void verifyFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ verifyBasicFieldTypeAnnotations(c);
+ verifyInnerFieldTypeAnnotations(c);
+ verifyArrayFieldTypeAnnotations(c);
+ verifyMapFieldTypeAnnotations(c);
+ }
+
+ private void verifyBasicFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno = c.getDeclaredField("typeAnnotatedBoolean").getAnnotatedType().getAnnotations()[0];
+ verifyTestAnn(fieldTA, anno, "field");
+ fieldTA = anno;
+ }
+
+ private void verifyInnerFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ AnnotatedType at = c.getDeclaredField("typeAnnotatedInner").getAnnotatedType();
+ Annotation anno = at.getAnnotations()[0];
+ verifyTestAnn(innerTA, anno, "inner");
+ innerTA = anno;
+ }
+
+ private void verifyArrayFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno;
+ AnnotatedType at;
+
+ at = c.getDeclaredField("typeAnnotatedArray").getAnnotatedType();
+ anno = at.getAnnotations()[0];
+ verifyTestAnn(arrayTA[0], anno, "array1");
+ arrayTA[0] = anno;
+
+ for (int i = 1; i <= 3; i++) {
+ at = ((AnnotatedArrayType) at).getAnnotatedGenericComponentType();
+ anno = at.getAnnotations()[0];
+ verifyTestAnn(arrayTA[i], anno, "array" + (i + 1));
+ arrayTA[i] = anno;
+ }
+ }
+
+ private void verifyMapFieldTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+
+ Annotation anno;
+ AnnotatedType atBase;
+ AnnotatedType atParameter;
+ atBase = c.getDeclaredField("typeAnnotatedMap").getAnnotatedType();
+
+ anno = atBase.getAnnotations()[0];
+ verifyTestAnn(mapTA[0], anno, "map1");
+ mapTA[0] = anno;
+
+ atParameter =
+ ((AnnotatedParameterizedType) atBase).
+ getAnnotatedActualTypeArguments()[0];
+ anno = ((AnnotatedWildcardType) atParameter).getAnnotations()[0];
+ verifyTestAnn(mapTA[1], anno, "map2");
+ mapTA[1] = anno;
+
+ anno =
+ ((AnnotatedWildcardType) atParameter).
+ getAnnotatedUpperBounds()[0].getAnnotations()[0];
+ verifyTestAnn(mapTA[2], anno, "map3");
+ mapTA[2] = anno;
+
+ atParameter =
+ ((AnnotatedParameterizedType) atBase).
+ getAnnotatedActualTypeArguments()[1];
+ anno = ((AnnotatedParameterizedType) atParameter).getAnnotations()[0];
+ verifyTestAnn(mapTA[3], anno, "map4");
+ mapTA[3] = anno;
+
+ anno =
+ ((AnnotatedParameterizedType) atParameter).
+ getAnnotatedActualTypeArguments()[0].getAnnotations()[0];
+ verifyTestAnn(mapTA[4], anno, "map5");
+ mapTA[4] = anno;
+ }
+
+ private void verifyMethodTypeAnnotations(Class c)
+ throws NoSuchFieldException, NoSuchMethodException {
+ Annotation anno;
+ Executable typeAnnotatedMethod =
+ c.getDeclaredMethod("typeAnnotatedMethod", TypeAnnotatedTestClass.class);
+
+ anno = typeAnnotatedMethod.getAnnotatedReturnType().getAnnotations()[0];
+ verifyTestAnn(returnTA, anno, "return");
+ returnTA = anno;
+
+ anno = typeAnnotatedMethod.getTypeParameters()[0].getAnnotations()[0];
+ verifyTestAnn(methodTypeParameterTA, anno, "methodTypeParameter");
+ methodTypeParameterTA = anno;
+
+ anno = typeAnnotatedMethod.getAnnotatedParameterTypes()[0].getAnnotations()[0];
+ verifyTestAnn(formalParameterTA, anno, "formalParameter");
+ formalParameterTA = anno;
+
+ anno = typeAnnotatedMethod.getAnnotatedExceptionTypes()[0].getAnnotations()[0];
+ verifyTestAnn(throwsTA, anno, "throws");
+ throwsTA = anno;
+ }
+
+ private static void verifyTestAnn(Annotation verifyAgainst, Annotation anno, String expectedSite) {
+ verifyTestAnnSite(anno, expectedSite);
+
+ // When called before transform verifyAgainst will be null, when called
+ // after transform it will be the annotation from before the transform
+ if (verifyAgainst != null) {
+ assertTrue(anno.equals(verifyAgainst),
+ "Annotations do not match before and after." +
+ " Before: \"" + verifyAgainst + "\", After: \"" + anno + "\"");
+ }
+ }
+
+ private static void verifyTestAnnSite(Annotation testAnn, String expectedSite) {
+ String expectedAnn = "@TestAnn(site=\"" + expectedSite + "\")";
+ assertTrue(testAnn.toString().equals(expectedAnn),
+ "Expected \"" + expectedAnn + "\", got \"" + testAnn + "\"");
+ }
+
+ public static class TypeAnnotatedTestClass <@TestAnn(site="classTypeParameter") S,T>
+ extends @TestAnn(site="extends") Thread
+ implements @TestAnn(site="implements") Runnable {
+
+ public @TestAnn(site="field") boolean typeAnnotatedBoolean;
+
+ public
+ RedefineAnnotations.
+ @TestAnn(site="inner") TypeAnnotatedTestClass
+ typeAnnotatedInner;
+
+ public
+ @TestAnn(site="array4") boolean
+ @TestAnn(site="array1") []
+ @TestAnn(site="array2") []
+ @TestAnn(site="array3") []
+ typeAnnotatedArray;
+
+ public @TestAnn(site="map1") Map
+ <@TestAnn(site="map2") ? extends @TestAnn(site="map3") String,
+ @TestAnn(site="map4") List<@TestAnn(site="map5") Object>> typeAnnotatedMap;
+
+ public int dummy1;
+ public int dummy2;
+ public int dummy3;
+
+ @TestAnn(site="return") <@TestAnn(site="methodTypeParameter") U,V> Class
+ typeAnnotatedMethod(@TestAnn(site="formalParameter") TypeAnnotatedTestClass arg)
+ throws @TestAnn(site="throws") ClassNotFoundException {
+
+ @TestAnn(site="local_variable_type") int foo = 0;
+ throw new ClassNotFoundException();
+ }
+
+ public void run() {}
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDeleteJmethod.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8181171
+ * @summary Test deleting static method pointing to by a jmethod
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/native/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineDeleteJmethod
+ */
+
+class B {
+ private static int deleteMe() { System.out.println("deleteMe called"); return 5; }
+ public static int callDeleteMe() { return deleteMe(); }
+}
+
+public class RedefineDeleteJmethod {
+
+ public static String newB =
+ "class B {" +
+ "public static int callDeleteMe() { return 6; }" +
+ "}";
+
+ public static String newerB =
+ "class B {" +
+ "private static int deleteMe() { System.out.println(\"deleteMe (2) called\"); return 7; }" +
+ "public static int callDeleteMe() { return deleteMe(); }" +
+ "}";
+
+
+ static {
+ System.loadLibrary("RedefineDeleteJmethod");
+ }
+
+ static native int jniCallDeleteMe();
+
+ static void test(int expected, boolean nsme_expected) throws Exception {
+ // Call through static method
+ int res = B.callDeleteMe();
+ System.out.println("Result = " + res);
+ if (res != expected) {
+ throw new Error("returned " + res + " expected " + expected);
+ }
+
+ // Call through jmethodID, saved from first call.
+ try {
+ res = jniCallDeleteMe();
+ if (nsme_expected) {
+ throw new RuntimeException("Failed, NoSuchMethodError expected");
+ }
+ if (res != expected) {
+ throw new Error("returned " + res + " expected " + expected);
+ }
+ } catch (NoSuchMethodError ex) {
+ if (!nsme_expected) {
+ throw new RuntimeException("Failed, NoSuchMethodError not expected");
+ }
+ System.out.println("Passed, NoSuchMethodError expected");
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ test(5, false);
+ RedefineClassHelper.redefineClass(B.class, newB);
+ test(6, true);
+ RedefineClassHelper.redefineClass(B.class, newerB);
+ test(7, true);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineDoubleDelete.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @bug 8178870 8010319
+ * @summary Redefine class with CFLH twice to test deleting the cached_class_file
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/native -Xlog:redefine+class+load+exceptions -agentlib:RedefineDoubleDelete -javaagent:redefineagent.jar RedefineDoubleDelete
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+// The ClassFileLoadHook for this class turns foo into faa and prints out faa.
+class RedefineDoubleDelete_B {
+ int faa() { System.out.println("foo"); return 1; }
+}
+
+public class RedefineDoubleDelete {
+
+ // Class gets a redefinition error because it adds a data member
+ public static String newB =
+ "class RedefineDoubleDelete_B {" +
+ " int count1 = 0;" +
+ "}";
+
+ public static String newerB =
+ "class RedefineDoubleDelete_B { " +
+ " int faa() { System.out.println(\"baa\"); return 2; }" +
+ "}";
+
+ public static void main(String args[]) throws Exception {
+
+ RedefineDoubleDelete_B b = new RedefineDoubleDelete_B();
+ int val = b.faa();
+ if (val != 1) {
+ throw new RuntimeException("return value wrong " + val);
+ }
+
+ // Redefine B twice to get cached_class_file in both B scratch classes
+ try {
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
+ } catch (java.lang.UnsupportedOperationException e) {
+ // this is expected
+ }
+ try {
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newB);
+ } catch (java.lang.UnsupportedOperationException e) {
+ // this is expected
+ }
+
+ // Do a full GC.
+ System.gc();
+
+ // Redefine with a compatible class
+ RedefineClassHelper.redefineClass(RedefineDoubleDelete_B.class, newerB);
+ val = b.faa();
+ if (val != 2) {
+ throw new RuntimeException("return value wrong " + val);
+ }
+
+ // Do another full GC to clean things up.
+ System.gc();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineFinalizer.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 6904403 8010319
+ * @summary Don't assert if we redefine finalize method
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineFinalizer
+ */
+
+/*
+ * Regression test for hitting:
+ *
+ * assert(f == k->has_finalizer()) failed: inconsistent has_finalizer
+ *
+ * when redefining finalizer method
+ */
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineFinalizer_B {
+ protected void finalize() {
+ // should be empty
+ }
+}
+
+public class RedefineFinalizer {
+
+ public static String newB =
+ "class RedefineFinalizer_B {" +
+ " protected void finalize() { " +
+ " System.out.println(\"Finalizer called\");" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ RedefineClassHelper.redefineClass(RedefineFinalizer_B.class, newB);
+
+ A a = new A();
+ }
+
+ static class A extends RedefineFinalizer_B {
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineInterfaceCall.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * @test
+ * @bug 8174962 8010319
+ * @summary Redefine class with interface method call
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+update*=trace RedefineInterfaceCall
+ */
+
+import static jdk.test.lib.Asserts.assertEquals;
+
+interface I1 { default int m() { return 0; } }
+interface I2 extends I1 {}
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineInterfaceCall_C implements I2 {
+ public int test(I2 i) {
+ return i.m(); // invokeinterface cpCacheEntry
+ }
+}
+
+public class RedefineInterfaceCall {
+
+ static String newI1 =
+ "interface I1 { default int m() { return 1; } }";
+
+ static String newC =
+ "class RedefineInterfaceCall_C implements I2 { " +
+ " public int test(I2 i) { " +
+ " return i.m(); " +
+ " } " +
+ "} ";
+
+ static int test(I2 i) {
+ return i.m(); // invokeinterface cpCacheEntry
+ }
+
+ public static void main(String[] args) throws Exception {
+ RedefineInterfaceCall_C c = new RedefineInterfaceCall_C();
+
+ assertEquals(test(c), 0);
+ assertEquals(c.test(c), 0);
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
+
+ assertEquals(c.test(c), 0);
+
+ RedefineClassHelper.redefineClass(I1.class, newI1);
+
+ assertEquals(test(c), 1);
+ assertEquals(c.test(c), 1);
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceCall_C.class, newC);
+
+ assertEquals(c.test(c), 1);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineInterfaceMethods.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8081800 8010319
+ * @summary Redefine private and default interface methods
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineInterfaceMethods
+ */
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+interface RedefineInterfaceMethods_B {
+ int ORIGINAL_RETURN = 1;
+ int NEW_RETURN = 2;
+ private int privateMethod() {
+ return ORIGINAL_RETURN;
+ }
+ public default int defaultMethod() {
+ return privateMethod();
+ }
+}
+
+public class RedefineInterfaceMethods {
+
+ static final int RET = -2;
+
+ public static String redefinedPrivateMethod =
+ "interface RedefineInterfaceMethods_B {" +
+ " int ORIGINAL_RETURN = 1;" +
+ " int NEW_RETURN = 2;" +
+ " private int privateMethod() {" +
+ " return NEW_RETURN;" +
+ " }" +
+ " public default int defaultMethod() {" +
+ " return privateMethod();" +
+ " }" +
+ "}";
+
+ public static String redefinedDefaultMethod =
+ "interface RedefineInterfaceMethods_B {" +
+ " int ORIGINAL_RETURN = 1;" +
+ " int NEW_RETURN = 2;" +
+ " private int privateMethod() {" +
+ " return ORIGINAL_RETURN;" +
+ " }" +
+ " public default int defaultMethod() {" +
+ " return RedefineInterfaceMethods.RET;" +
+ " }" +
+ "}";
+
+ static class Impl implements RedefineInterfaceMethods_B {
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ Impl impl = new Impl();
+
+ int res = impl.defaultMethod();
+ if (res != RedefineInterfaceMethods_B.ORIGINAL_RETURN)
+ throw new Error("defaultMethod returned " + res +
+ " expected " + RedefineInterfaceMethods_B.ORIGINAL_RETURN);
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedPrivateMethod);
+
+ res = impl.defaultMethod();
+ if (res != RedefineInterfaceMethods_B.NEW_RETURN)
+ throw new Error("defaultMethod returned " + res +
+ " expected " + RedefineInterfaceMethods_B.NEW_RETURN);
+
+ System.gc();
+
+ RedefineClassHelper.redefineClass(RedefineInterfaceMethods_B.class, redefinedDefaultMethod);
+
+ res = impl.defaultMethod();
+ if (res != RET)
+ throw new Error("defaultMethod returned " + res +
+ " expected " + RET);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineLeak.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @library /test/lib
+ * @summary Test that redefinition reuses metaspace blocks that are freed
+ * @modules java.base/jdk.internal.misc
+ * @modules java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineLeak buildagent
+ * @run main/othervm/timeout=6000 RedefineLeak runtest
+ */
+
+import java.io.FileNotFoundException;
+import java.io.PrintWriter;
+import java.lang.RuntimeException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import java.lang.instrument.IllegalClassFormatException;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+public class RedefineLeak {
+ static class Tester {}
+
+ static class LoggingTransformer implements ClassFileTransformer {
+ static int transformCount = 0;
+
+ public LoggingTransformer() {}
+
+ public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+
+ transformCount++;
+ if (transformCount % 1000 == 0) System.out.println("transformCount:" + transformCount);
+ return null;
+ }
+ }
+
+ public static void premain(String agentArgs, Instrumentation inst) throws Exception {
+ LoggingTransformer t = new LoggingTransformer();
+ inst.addTransformer(t, true);
+ {
+ Class demoClass = Class.forName("RedefineLeak$Tester");
+
+ for (int i = 0; i < 10000; i++) {
+ inst.retransformClasses(demoClass);
+ }
+ }
+ System.gc();
+ }
+ private static void buildAgent() {
+ try {
+ ClassFileInstaller.main("RedefineLeak");
+ } catch (Exception e) {
+ throw new RuntimeException("Could not write agent classfile", e);
+ }
+
+ try {
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: RedefineLeak");
+ pw.println("Agent-Class: RedefineLeak");
+ pw.println("Can-Redefine-Classes: true");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+ } catch (FileNotFoundException e) {
+ throw new RuntimeException("Could not write manifest file for the agent", e);
+ }
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineLeak.class" })) {
+ throw new RuntimeException("Could not write the agent jar file");
+ }
+ }
+ public static void main(String argv[]) throws Exception {
+ if (argv.length == 1 && argv[0].equals("buildagent")) {
+ buildAgent();
+ return;
+ }
+ if (argv.length == 1 && argv[0].equals("runtest")) {
+ // run outside of jtreg to not OOM on jtreg classes that are loaded after metaspace is full
+ String[] javaArgs1 = { "-XX:MetaspaceSize=12m", "-XX:MaxMetaspaceSize=12m",
+ "-javaagent:redefineagent.jar", "RedefineLeak"};
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(javaArgs1);
+
+ OutputAnalyzer output = new OutputAnalyzer(pb.start());
+ output.shouldContain("transformCount:10000");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefinePreviousVersions.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+/*
+ * @test
+ * @bug 8165246 8010319
+ * @summary Test has_previous_versions flag and processing during class unloading.
+ * @requires vm.opt.final.ClassUnloading
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm RedefinePreviousVersions test
+ */
+
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+// package access top-level classes to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefinePreviousVersions_B { }
+
+class RedefinePreviousVersions_Running {
+ public static volatile boolean stop = false;
+ public static volatile boolean running = false;
+ static void localSleep() {
+ try {
+ Thread.sleep(10); // sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ running = true;
+ while (!stop) { localSleep(); }
+ }
+}
+
+
+
+public class RedefinePreviousVersions {
+
+ public static String newB =
+ "class RedefinePreviousVersions_B {" +
+ "}";
+
+ public static String newRunning =
+ "class RedefinePreviousVersions_Running {" +
+ " public static volatile boolean stop = true;" +
+ " public static volatile boolean running = true;" +
+ " static void localSleep() { }" +
+ " public static void infinite() { }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+
+ if (args.length > 0) {
+
+ // java -javaagent:redefineagent.jar -Xlog:stuff RedefinePreviousVersions
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-javaagent:redefineagent.jar",
+ "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
+ "RedefinePreviousVersions");
+ new OutputAnalyzer(pb.start())
+ .shouldContain("Class unloading: has_previous_versions = false")
+ .shouldContain("Class unloading: has_previous_versions = true")
+ .shouldHaveExitValue(0);
+ return;
+ }
+
+ // Redefine a class and create some garbage
+ // Since there are no methods running, the previous version is never added to the
+ // previous_version_list and the flag _has_previous_versions should stay false
+ RedefineClassHelper.redefineClass(RedefinePreviousVersions_B.class, newB);
+
+ for (int i = 0; i < 10 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ // Start a class that has a method running
+ new Thread() {
+ public void run() {
+ RedefinePreviousVersions_Running.infinite();
+ }
+ }.start();
+
+ while (!RedefinePreviousVersions_Running.running) {
+ Thread.sleep(10); // sleep for 10 ms
+ }
+
+ // Since a method of newRunning is running, this class should be added to the previous_version_list
+ // of Running, and _has_previous_versions should return true at class unloading.
+ RedefineClassHelper.redefineClass(RedefinePreviousVersions_Running.class, newRunning);
+
+ for (int i = 0; i < 10 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ // purge should clean everything up, except Xcomp it might not.
+ RedefinePreviousVersions_Running.stop = true;
+
+ for (int i = 0; i < 10 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethods.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,150 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8055008 8197901 8010319
+ * @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace,class+loader+data=debug,safepoint+cleanup,gc+phases=debug:rt.log RedefineRunningMethods
+ */
+
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+class RedefineRunningMethods_B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try{
+ Thread.currentThread().sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void infinite_emcp() {
+ while (!stop) { count2++; localSleep(); }
+ }
+}
+
+public class RedefineRunningMethods {
+
+ public static String newB =
+ "class RedefineRunningMethods_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void infinite_emcp() { " +
+ " while (!stop) { count2++; localSleep(); }" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethods_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.currentThread().sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void infinite_emcp() { " +
+ " System.out.println(\"infinite_emcp now obsolete called\");" +
+ " }" +
+ "}";
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ RedefineRunningMethods_B.infinite();
+ }
+ }.start();
+
+ new Thread() {
+ public void run() {
+ RedefineRunningMethods_B.infinite_emcp();
+ }
+ }.start();
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, newB);
+
+ System.gc();
+
+ RedefineRunningMethods_B.infinite();
+
+ // Start a thread with the second version of infinite_emcp running
+ new Thread() {
+ public void run() {
+ RedefineRunningMethods_B.infinite_emcp();
+ }
+ }.start();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethods_B.class, evenNewerB);
+ System.gc();
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethods_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineRunningMethods_B.infinite_emcp();
+
+ // purge should clean everything up.
+ RedefineRunningMethods_B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethods_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithBacktrace.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,196 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/*
+ * @test
+ * @bug 8087315 8010319
+ * @summary Get old method's stack trace elements after GC
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar RedefineRunningMethodsWithBacktrace
+ */
+
+import static jdk.test.lib.Asserts.*;
+
+// package access top-level class to avoid problem with RedefineClassHelper
+// and nested types.
+
+class RedefineRunningMethodsWithBacktrace_B {
+ static int count1 = 0;
+ static int count2 = 0;
+ public static volatile boolean stop = false;
+ static void localSleep() {
+ try {
+ Thread.sleep(10);//sleep for 10 ms
+ } catch(InterruptedException ie) {
+ }
+ }
+
+ public static void infinite() {
+ while (!stop) { count1++; localSleep(); }
+ }
+ public static void throwable() {
+ // add some stuff to the original constant pool
+ String s1 = new String ("string1");
+ String s2 = new String ("string2");
+ String s3 = new String ("string3");
+ String s4 = new String ("string4");
+ String s5 = new String ("string5");
+ String s6 = new String ("string6");
+ String s7 = new String ("string7");
+ String s8 = new String ("string8");
+ String s9 = new String ("string9");
+ String s10 = new String ("string10");
+ String s11 = new String ("string11");
+ String s12 = new String ("string12");
+ String s13 = new String ("string13");
+ String s14 = new String ("string14");
+ String s15 = new String ("string15");
+ String s16 = new String ("string16");
+ String s17 = new String ("string17");
+ String s18 = new String ("string18");
+ String s19 = new String ("string19");
+ throw new RuntimeException("throwable called");
+ }
+}
+
+public class RedefineRunningMethodsWithBacktrace {
+
+ public static String newB =
+ "class RedefineRunningMethodsWithBacktrace_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.sleep(10);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { " +
+ " System.out.println(\"infinite called\");" +
+ " }" +
+ " public static void throwable() { " +
+ " throw new RuntimeException(\"throwable called\");" +
+ " }" +
+ "}";
+
+ public static String evenNewerB =
+ "class RedefineRunningMethodsWithBacktrace_B {" +
+ " static int count1 = 0;" +
+ " static int count2 = 0;" +
+ " public static volatile boolean stop = false;" +
+ " static void localSleep() { " +
+ " try{ " +
+ " Thread.sleep(1);" +
+ " } catch(InterruptedException ie) { " +
+ " } " +
+ " } " +
+ " public static void infinite() { }" +
+ " public static void throwable() { " +
+ " throw new RuntimeException(\"throwable called\");" +
+ " }" +
+ "}";
+
+ private static void touchRedefinedMethodInBacktrace(Throwable throwable) {
+ System.out.println("touchRedefinedMethodInBacktrace: ");
+ throwable.printStackTrace(); // this actually crashes with the bug in
+ // java_lang_StackTraceElement::create()
+
+ // Make sure that we can convert the backtrace, which is referring to
+ // the redefined method, to a StrackTraceElement[] without crashing.
+ StackTraceElement[] stackTrace = throwable.getStackTrace();
+ for (int i = 0; i < stackTrace.length; i++) {
+ StackTraceElement frame = stackTrace[i];
+ assertNotNull(frame.getClassName(),
+ "\nTest failed: trace[" + i + "].getClassName() returned null");
+ assertNotNull(frame.getMethodName(),
+ "\nTest failed: trace[" + i + "].getMethodName() returned null");
+ }
+ }
+
+ private static Throwable getThrowableInB() {
+ Throwable t = null;
+ try {
+ RedefineRunningMethodsWithBacktrace_B.throwable();
+ } catch (Exception e) {
+ t = e;
+ // Don't print here because Throwable will cache the constructed stacktrace
+ // e.printStackTrace();
+ }
+ return t;
+ }
+
+
+ public static void main(String[] args) throws Exception {
+
+ new Thread() {
+ public void run() {
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+ }
+ }.start();
+
+ Throwable t1 = getThrowableInB();
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, newB);
+
+ System.gc();
+
+ Throwable t2 = getThrowableInB();
+
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+
+ for (int i = 0; i < 20 ; i++) {
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ RedefineClassHelper.redefineClass(RedefineRunningMethodsWithBacktrace_B.class, evenNewerB);
+ System.gc();
+
+ Throwable t3 = getThrowableInB();
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+
+ touchRedefinedMethodInBacktrace(t1);
+ touchRedefinedMethodInBacktrace(t2);
+ touchRedefinedMethodInBacktrace(t3);
+
+ // purge should clean everything up.
+ RedefineRunningMethodsWithBacktrace_B.stop = true;
+
+ for (int i = 0; i < 20 ; i++) {
+ RedefineRunningMethodsWithBacktrace_B.infinite();
+ String s = new String("some garbage");
+ System.gc();
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRunningMethodsWithResolutionErrors.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8076110
+ * @summary Redefine running methods that have cached resolution errors
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace RedefineRunningMethodsWithResolutionErrors
+ */
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
+
+import java.lang.reflect.InvocationTargetException;
+
+public class RedefineRunningMethodsWithResolutionErrors extends ClassLoader implements Opcodes {
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals("C")) {
+ byte[] b = loadC(false);
+ return defineClass(name, b, 0, b.length);
+ } else {
+ return super.findClass(name);
+ }
+ }
+
+ private static byte[] loadC(boolean redefine) {
+ ClassWriter cw = new ClassWriter(0);
+
+ cw.visit(52, ACC_SUPER | ACC_PUBLIC, "C", null, "java/lang/Object", null);
+ {
+ MethodVisitor mv;
+
+ mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "m", "()V", null, null);
+ mv.visitCode();
+
+ // First time we run we will:
+ // 1) Cache resolution errors
+ // 2) Redefine the class / method
+ // 3) Try to read the resolution errors that were cached
+ //
+ // The redefined method will never run, throw error to be sure
+ if (redefine) {
+ createThrowRuntimeExceptionCode(mv, "The redefined method was called");
+ } else {
+ createMethodBody(mv);
+ }
+ mv.visitMaxs(3, 0);
+ mv.visitEnd();
+ }
+ cw.visitEnd();
+ return cw.toByteArray();
+ }
+
+ private static void createMethodBody(MethodVisitor mv) {
+ Label classExists = new Label();
+
+ // Cache resolution errors
+ createLoadNonExistentClassCode(mv, classExists);
+
+ // Redefine our own class and method
+ mv.visitMethodInsn(INVOKESTATIC, "RedefineRunningMethodsWithResolutionErrors", "redefine", "()V");
+
+ // Provoke the same error again to make sure the resolution error cache works
+ createLoadNonExistentClassCode(mv, classExists);
+
+ // Test passed
+ mv.visitInsn(RETURN);
+
+ mv.visitFrame(F_SAME, 0, new Object[0], 0, new Object[0]);
+ mv.visitLabel(classExists);
+
+ createThrowRuntimeExceptionCode(mv, "Loaded class that shouldn't exist (\"NonExistentClass\")");
+ }
+
+ private static void createLoadNonExistentClassCode(MethodVisitor mv, Label classExists) {
+ Label tryLoadBegin = new Label();
+ Label tryLoadEnd = new Label();
+ Label catchLoadBlock = new Label();
+ mv.visitTryCatchBlock(tryLoadBegin, tryLoadEnd, catchLoadBlock, "java/lang/NoClassDefFoundError");
+
+ // Try to load a class that does not exist to provoke resolution errors
+ mv.visitLabel(tryLoadBegin);
+ mv.visitMethodInsn(INVOKESTATIC, "NonExistentClass", "nonExistentMethod", "()V");
+ mv.visitLabel(tryLoadEnd);
+
+ // No NoClassDefFoundError means NonExistentClass existed, which shouldn't happen
+ mv.visitJumpInsn(GOTO, classExists);
+
+ mv.visitFrame(F_SAME1, 0, new Object[0], 1, new Object[] { "java/lang/NoClassDefFoundError" });
+ mv.visitLabel(catchLoadBlock);
+
+ // Ignore the expected NoClassDefFoundError
+ mv.visitInsn(POP);
+ }
+
+ private static void createThrowRuntimeExceptionCode(MethodVisitor mv, String msg) {
+ mv.visitTypeInsn(NEW, "java/lang/RuntimeException");
+ mv.visitInsn(DUP);
+ mv.visitLdcInsn(msg);
+ mv.visitMethodInsn(INVOKESPECIAL, "java/lang/RuntimeException", "<init>", "(Ljava/lang/String;)V");
+ mv.visitInsn(ATHROW);
+ }
+
+ private static Class<?> c;
+
+ public static void redefine() throws Exception {
+ RedefineClassHelper.redefineClass(c, loadC(true));
+ }
+
+ public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+ c = Class.forName("C", true, new RedefineRunningMethodsWithResolutionErrors());
+ c.getMethod("m").invoke(null);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSubtractLambdaExpression.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/*
+ * @test
+ * @bug 8193524
+ * @summary Redefine a class' public static method that contains a lambda expression
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm -javaagent:redefineagent.jar -Xlog:redefine+class*=trace RedefineSubtractLambdaExpression
+ */
+
+interface MathOperation {
+ public int operation(int a, int b);
+}
+
+class B {
+ public static int operate(int a, int b, MathOperation mathOperation) {
+ return mathOperation.operation(a, b);
+ }
+ static int test_math(String p) {
+ System.out.println(p + " from class B's test_math method");
+ MathOperation subtraction = (int a, int b) -> a - b;
+ MathOperation addition = (int a, int b) -> a + b;
+ return operate(10, 5, addition);
+ }
+}
+
+public class RedefineSubtractLambdaExpression {
+
+ public static String newB =
+ "class B {" +
+ " public static int operate(int a, int b, MathOperation mathOperation) {" +
+ " return mathOperation.operation(a, b);" +
+ " }" +
+ " static int test_math(String p) {" +
+ " MathOperation subtraction = (int a, int b) -> a - b;" +
+ " return operate(10, 5, subtraction);" +
+ " }" +
+ "}";
+
+ public static void main(String[] args) throws Exception {
+ int res = B.test_math("Hello");
+ System.out.println("Result = " + res);
+ if (res != 15) {
+ throw new Error("test_math returned " + res + " expected " + 15);
+ }
+ RedefineClassHelper.redefineClass(B.class, newB);
+
+ res = B.test_math("Hello");
+ if (res != 5)
+ throw new Error("test_math returned " + res + " expected " + 5);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RetransformClassesZeroLength.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2018, 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.
+ */
+
+/**
+ * @test
+ * @bug 8198393
+ * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
+ * @library /test/lib
+ * @modules java.instrument
+ * @compile RetransformClassesZeroLength.java
+ * @run main RetransformClassesZeroLength
+ */
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+
+import jdk.test.lib.process.ProcessTools;
+
+
+public class RetransformClassesZeroLength {
+
+ private static String manifest =
+ "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
+ + "Can-Retransform-Classes: true\n";
+
+ private static String CP = System.getProperty("test.classes");
+
+ public static void main(String args[]) throws Throwable {
+ String agentJar = buildAgent();
+ ProcessTools.executeProcess(
+ ProcessTools.createJavaProcessBuilder(
+ "-javaagent:" + agentJar,
+ "-version")
+ ).shouldHaveExitValue(0);
+ }
+
+ private static String buildAgent() throws Exception {
+ Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+ String jarPath = jar.toAbsolutePath().toString();
+ ClassFileInstaller.writeJar(jarPath,
+ ClassFileInstaller.Manifest.fromString(manifest),
+ RetransformClassesZeroLength.class.getName());
+ return jarPath;
+ }
+
+
+ public static class Agent implements ClassFileTransformer {
+ public static void premain(String args, Instrumentation inst) {
+ inst.addTransformer(new NoOpTransformer());
+ try {
+ inst.retransformClasses(new Class[0]);
+ } catch (UnmodifiableClassException ex) {
+ throw new AssertionError(ex);
+ }
+ }
+ }
+
+ private static class NoOpTransformer implements ClassFileTransformer {
+ @Override
+ public byte[] transform(ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer
+ ) throws IllegalClassFormatException {
+ return null; // no transform
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestLambdaFormRetransformation.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 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.
+ */
+
+/**
+ * @test
+ * @bug 8008678
+ * @summary JSR 292: constant pool reconstitution must support pseudo strings
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.instrument
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
+ * @run main TestLambdaFormRetransformation
+ */
+
+import java.io.IOException;
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.lang.instrument.UnmodifiableClassException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.ProtectionDomain;
+import java.util.Arrays;
+
+import jdk.test.lib.process.ExitCode;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestLambdaFormRetransformation {
+ private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
+ "Premain-Class: %s\n" +
+ "Can-Retransform-Classes: true\n",
+ Agent.class.getName());
+
+ private static String CP = System.getProperty("test.classes");
+
+ public static void main(String args[]) throws Throwable {
+ Path agent = TestLambdaFormRetransformation.buildAgent();
+ OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
+ agent.toAbsolutePath().toString(), "-version");
+ oa.shouldHaveExitValue(ExitCode.OK.value);
+ }
+
+ private static Path buildAgent() throws IOException {
+ Path manifest = TestLambdaFormRetransformation.createManifest();
+ Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
+
+ String[] args = new String[] {
+ "-cfm",
+ jar.toAbsolutePath().toString(),
+ manifest.toAbsolutePath().toString(),
+ "-C",
+ TestLambdaFormRetransformation.CP,
+ Agent.class.getName() + ".class"
+ };
+
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+
+ if (!jarTool.run(args)) {
+ throw new Error("jar failed: args=" + Arrays.toString(args));
+ }
+ return jar;
+ }
+
+ private static Path createManifest() throws IOException {
+ Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
+ byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
+ Files.write(manifest, manifestBytes);
+ return manifest;
+ }
+}
+
+class Agent implements ClassFileTransformer {
+ private static Runnable lambda = () -> {
+ System.out.println("I'll crash you!");
+ };
+
+ public static void premain(String args, Instrumentation instrumentation) {
+ if (!instrumentation.isRetransformClassesSupported()) {
+ System.out.println("Class retransformation is not supported.");
+ return;
+ }
+ System.out.println("Calling lambda to ensure that lambda forms were created");
+
+ Agent.lambda.run();
+
+ System.out.println("Registering class file transformer");
+
+ instrumentation.addTransformer(new Agent());
+
+ for (Class c : instrumentation.getAllLoadedClasses()) {
+ if (c.getName().contains("LambdaForm") &&
+ instrumentation.isModifiableClass(c)) {
+ System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
+ try {
+ instrumentation.retransformClasses(c);
+ } catch (UnmodifiableClassException e) {
+ throw new AssertionError("Modification of modifiable class " +
+ "caused UnmodifiableClassException", e);
+ }
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ }
+
+ @Override
+ public byte[] transform(ClassLoader loader,
+ String className,
+ Class<?> classBeingRedefined,
+ ProtectionDomain protectionDomain,
+ byte[] classfileBuffer
+ ) throws IllegalClassFormatException {
+ System.out.println("Transforming " + className);
+ return classfileBuffer.clone();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestMultipleClasses.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @bug 8139551
+ * @summary Scalability problem with redefinition - multiple code cache walks
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * @modules java.compiler
+ * java.instrument
+ * jdk.jartool/sun.tools.jar
+ * @run main RedefineClassHelper
+ * @run main/othervm/timeout=180 -javaagent:redefineagent.jar -XX:CompileThreshold=100 -Xlog:redefine+class+nmethod=debug TestMultipleClasses
+ */
+
+import java.lang.instrument.*;
+import java.lang.reflect.*;
+import jdk.test.lib.compiler.InMemoryJavaCompiler;
+
+public class TestMultipleClasses extends ClassLoader {
+
+ public static String B(int count) {
+ return new String("public class B" + count + " {" +
+ " public static void compiledMethod() { " +
+ " try{" +
+ " Thread.sleep(1); " +
+ " } catch(InterruptedException ie) {" +
+ " }" +
+ " }" +
+ "}");
+ }
+
+ static String newB(int count) {
+ return new String("public class B" + count + " {" +
+ " public static void compiledMethod() { " +
+ " System.out.println(\"compiledMethod called " + count + "\");" +
+ " }" +
+ "}");
+ }
+
+ static int index = 0;
+
+ @Override
+ protected Class<?> findClass(String name) throws ClassNotFoundException {
+ if (name.equals("B" + index)) {
+ byte[] b = InMemoryJavaCompiler.compile(name, B(index));
+ return defineClass(name, b, 0, b.length);
+ } else {
+ return super.findClass(name);
+ }
+ }
+
+ 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);
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+
+ final int numberOfClasses = 20;
+ Class[] classes = new Class[numberOfClasses];
+ byte[][] newClass = new byte[numberOfClasses][];
+ ClassDefinition[] defs = new ClassDefinition[numberOfClasses];
+
+ TestMultipleClasses loader = new TestMultipleClasses();
+
+ // Load and start all the classes.
+ for (index = 0; index < numberOfClasses; index++) {
+ String name = new String("B" + index);
+ Class c = loader.findClass(name);
+
+ runCompiledMethodMethods(c, 500);
+ // Make class definition for redefinition
+ classes[index] = c;
+ newClass[index] = InMemoryJavaCompiler.compile(c.getName(), newB(index));
+ defs[index] = new ClassDefinition(c, newClass[index]);
+ }
+
+ long startTime = System.currentTimeMillis();
+
+ // Redefine all classes.
+ RedefineClassHelper.instrumentation.redefineClasses(defs);
+
+ long endTime = System.currentTimeMillis();
+
+ System.out.println("Redefinition took " + (endTime - startTime) + " milliseconds");
+
+ System.gc();
+
+ // Run all new classes.
+ for (index = 0; index < numberOfClasses; index++) {
+ runCompiledMethodMethods(classes[index], 1);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineObject.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+import java.io.PrintWriter;
+
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+
+/*
+ * Test to redefine java/lang/Object and verify that it doesn't crash on vtable
+ * call on basic array type.
+ * Test to redefine java/lang/ClassLoader and java/lang/reflect/Method to make
+ * sure cached versions used afterward are the current version.
+ *
+ * @test
+ * @bug 8005056
+ * @bug 8009728
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.instrument
+ * java.management
+ * @build Agent
+ * @run driver ClassFileInstaller Agent
+ * @run main TestRedefineObject
+ * @run main/othervm -javaagent:agent.jar -Xlog:redefine+class+load=debug,redefine+class+timer=info Agent
+ */
+public class TestRedefineObject {
+ public static void main(String[] args) throws Exception {
+
+ PrintWriter pw = new PrintWriter("MANIFEST.MF");
+ pw.println("Premain-Class: Agent");
+ pw.println("Can-Retransform-Classes: true");
+ pw.close();
+
+ ProcessBuilder pb = new ProcessBuilder();
+ pb.command(new String[] { JDKToolFinder.getJDKTool("jar"), "cmf", "MANIFEST.MF", "agent.jar", "Agent.class"});
+ pb.start().waitFor();
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/TestRedefineWithUnresolvedClass.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+/*
+ * @test
+ * @summary Redefine a class with an UnresolvedClass reference in the constant pool.
+ * @bug 8035150
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ * java.compiler
+ * java.instrument
+ * java.management
+ * jdk.jartool/sun.tools.jar
+ * jdk.internal.jvmstat/sun.jvmstat.monitor
+ * @build UnresolvedClassAgent
+ * @run main TestRedefineWithUnresolvedClass
+ */
+
+import java.io.File;
+import java.util.Arrays;
+
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.process.ProcessTools;
+
+public class TestRedefineWithUnresolvedClass {
+
+ final static String slash = File.separator;
+ final static String testClasses = System.getProperty("test.classes") + slash;
+
+ public static void main(String... args) throws Throwable {
+ // delete this class to cause a NoClassDefFoundError
+ File unresolved = new File(testClasses, "MyUnresolvedClass.class");
+ if (unresolved.exists() && !unresolved.delete()) {
+ throw new Exception("Could not delete: " + unresolved);
+ }
+
+ // build the javaagent
+ buildJar("UnresolvedClassAgent");
+
+ // launch a VM with the javaagent
+ launchTest();
+ }
+
+ private static void buildJar(String jarName) throws Throwable {
+ String testSrc = System.getProperty("test.src", "?") + slash;
+
+ String jarPath = String.format("%s%s.jar", testClasses, jarName);
+ String manifestPath = String.format("%s%s.mf", testSrc, jarName);
+ String className = String.format("%s.class", jarName);
+
+ String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
+
+ System.out.println("Running jar " + Arrays.toString(args));
+ sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
+ if (!jarTool.run(args)) {
+ throw new Exception("jar failed: args=" + Arrays.toString(args));
+ }
+ }
+
+ private static void launchTest() throws Throwable {
+ String[] args = {
+ "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
+ "-Dtest.classes=" + testClasses,
+ "UnresolvedClassAgent" };
+ OutputAnalyzer output = ProcessTools.executeTestJvm(args);
+ output.shouldHaveExitValue(0);
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/UnresolvedClassAgent.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.lang.instrument.ClassDefinition;
+import java.lang.instrument.Instrumentation;
+
+/*
+ * This class is present during compilation, but will be deleted before execution.
+ */
+class MyUnresolvedClass {
+ static void bar() {
+ }
+}
+
+class MyRedefinedClass {
+ static void foo() {
+ MyUnresolvedClass.bar();
+ }
+}
+
+public class UnresolvedClassAgent {
+ public static void main(String... args) {
+ }
+
+ public static void premain(String args, Instrumentation inst) throws Exception {
+ try {
+ MyRedefinedClass.foo();
+ } catch(NoClassDefFoundError err) {
+ System.out.println("NoClassDefFoundError (expected)");
+ }
+
+ File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
+ byte[] buf = new byte[(int)f.length()];
+ try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
+ dis.readFully(buf);
+ }
+ ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
+ inst.redefineClasses(new ClassDefinition[] {cd});
+
+ try {
+ MyRedefinedClass.foo();
+ } catch(NoClassDefFoundError err) {
+ System.out.println("NoClassDefFoundError (expected again)");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/UnresolvedClassAgent.mf Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Premain-Class: UnresolvedClassAgent
+Can-Redefine-Classes: true
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/WalkThroughInvoke.java Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+import java.lang.reflect.*;
+
+public class WalkThroughInvoke {
+ public void stackWalk() {
+ try {
+ Class b = Object.class;
+ SecurityManager sm = new SecurityManager();
+ // Walks the stack with Method.invoke in the stack (which is the
+ // purpose of the test) before it gets an AccessControlException.
+ sm.checkPermission(new RuntimePermission("accessDeclaredMembers"));
+ } catch (java.security.AccessControlException e) {
+ // Ignoring an 'AccessControlException' exception since
+ // it is expected as part of this test.
+ }
+ }
+};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/libRedefineDeleteJmethod.c Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+
+#include <jni.h>
+
+jmethodID mid;
+jclass cls;
+static int count = 0;
+
+JNIEXPORT jint JNICALL
+Java_RedefineDeleteJmethod_jniCallDeleteMe(JNIEnv* env, jobject obj) {
+
+ if (count == 0) {
+ count++;
+ cls = (*env)->FindClass(env, "B");
+ if (NULL == cls) {
+ (*env)->FatalError(env, "could not find class");
+ }
+
+ mid = (*env)->GetStaticMethodID(env, cls, "deleteMe", "()I");
+ if (NULL == mid) {
+ (*env)->FatalError(env, "could not find method");
+ }
+ }
+
+ return (*env)->CallStaticIntMethod(env, cls, mid);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/libRedefineDoubleDelete.c Tue Mar 19 14:22:47 2019 -0400
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+static jvmtiEnv *jvmti = NULL;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_9;
+}
+
+
+static jint newClassDataLen = 0;
+static unsigned char* newClassData = NULL;
+
+static jint
+getBytecodes(jvmtiEnv *jvmti_env,
+ jint class_data_len, const unsigned char* class_data) {
+ int i;
+ jint res;
+
+ newClassDataLen = class_data_len;
+ res = (*jvmti_env)->Allocate(jvmti_env, newClassDataLen, &newClassData);
+ if (res != JNI_OK) {
+ printf(" Unable to allocate bytes\n");
+ return JNI_ERR;
+ }
+ for (i = 0; i < newClassDataLen; i++) {
+ newClassData[i] = class_data[i];
+ // Rewrite oo in class to aa
+ if (i > 0 && class_data[i] == 'o' && class_data[i-1] == 'o') {
+ newClassData[i] = newClassData[i-1] = 'a';
+ }
+ }
+ printf(" ... copied bytecode: %d bytes\n", (int)newClassDataLen);
+ return JNI_OK;
+}
+
+
+static void JNICALL
+Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, JNIEnv *env,
+ jclass class_being_redefined,
+ jobject loader, const char* name, jobject protection_domain,
+ jint class_data_len, const unsigned char* class_data,
+ jint *new_class_data_len, unsigned char** new_class_data) {
+ if (name != NULL && strcmp(name, "RedefineDoubleDelete$B") == 0) {
+ if (newClassData == NULL) {
+ jint res = getBytecodes(jvmti_env, class_data_len, class_data);
+ if (res == JNI_ERR) {
+ printf(">>> ClassFileLoadHook event: class name %s FAILED\n", name);
+ return;
+ }
+ // Only change for first CFLH event.
+ *new_class_data_len = newClassDataLen;
+ *new_class_data = newClassData;
+ }
+ printf(">>> ClassFileLoadHook event: class name %s\n", name);
+ }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res, size;
+ jvmtiCapabilities caps;
+ jvmtiEventCallbacks callbacks;
+ jvmtiError err;
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf(" Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ printf("Enabling following capabilities: can_generate_all_class_hook_events, "
+ "can_retransform_classes, can_redefine_classes");
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_all_class_hook_events = 1;
+ caps.can_retransform_classes = 1;
+ caps.can_redefine_classes = 1;
+ printf("\n");
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ size = (jint)sizeof(callbacks);
+
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
+
+ err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- a/test/hotspot/jtreg/serviceability/jvmti/RetransformClassesZeroLength.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2018, 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
- * @bug 8198393
- * @summary Instrumentation.retransformClasses(new Class[0]) should be NOP
- * @library /test/lib
- * @modules java.instrument
- * @compile RetransformClassesZeroLength.java
- * @run main RetransformClassesZeroLength
- */
-
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.ProtectionDomain;
-
-import jdk.test.lib.process.ProcessTools;
-
-
-public class RetransformClassesZeroLength {
-
- private static String manifest =
- "Premain-Class: " + RetransformClassesZeroLength.Agent.class.getName() + "\n"
- + "Can-Retransform-Classes: true\n";
-
- private static String CP = System.getProperty("test.classes");
-
- public static void main(String args[]) throws Throwable {
- String agentJar = buildAgent();
- ProcessTools.executeProcess(
- ProcessTools.createJavaProcessBuilder(
- "-javaagent:" + agentJar,
- "-version")
- ).shouldHaveExitValue(0);
- }
-
- private static String buildAgent() throws Exception {
- Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
- String jarPath = jar.toAbsolutePath().toString();
- ClassFileInstaller.writeJar(jarPath,
- ClassFileInstaller.Manifest.fromString(manifest),
- RetransformClassesZeroLength.class.getName());
- return jarPath;
- }
-
-
- public static class Agent implements ClassFileTransformer {
- public static void premain(String args, Instrumentation inst) {
- inst.addTransformer(new NoOpTransformer());
- try {
- inst.retransformClasses(new Class[0]);
- } catch (UnmodifiableClassException ex) {
- throw new AssertionError(ex);
- }
- }
- }
-
- private static class NoOpTransformer implements ClassFileTransformer {
- @Override
- public byte[] transform(ClassLoader loader,
- String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer
- ) throws IllegalClassFormatException {
- return null; // no transform
- }
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/TestLambdaFormRetransformation.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,141 +0,0 @@
-/*
- * Copyright (c) 2015, 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.
- *
- * 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
- * @bug 8008678
- * @summary JSR 292: constant pool reconstitution must support pseudo strings
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.instrument
- * java.management
- * jdk.jartool/sun.tools.jar
- * @compile -XDignore.symbol.file TestLambdaFormRetransformation.java
- * @run main TestLambdaFormRetransformation
- */
-
-import java.io.IOException;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
-import java.lang.instrument.Instrumentation;
-import java.lang.instrument.UnmodifiableClassException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.security.ProtectionDomain;
-import java.util.Arrays;
-
-import jdk.test.lib.process.ExitCode;
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestLambdaFormRetransformation {
- private static String MANIFEST = String.format("Manifest-Version: 1.0\n" +
- "Premain-Class: %s\n" +
- "Can-Retransform-Classes: true\n",
- Agent.class.getName());
-
- private static String CP = System.getProperty("test.classes");
-
- public static void main(String args[]) throws Throwable {
- Path agent = TestLambdaFormRetransformation.buildAgent();
- OutputAnalyzer oa = ProcessTools.executeTestJvm("-javaagent:" +
- agent.toAbsolutePath().toString(), "-version");
- oa.shouldHaveExitValue(ExitCode.OK.value);
- }
-
- private static Path buildAgent() throws IOException {
- Path manifest = TestLambdaFormRetransformation.createManifest();
- Path jar = Files.createTempFile(Paths.get("."), null, ".jar");
-
- String[] args = new String[] {
- "-cfm",
- jar.toAbsolutePath().toString(),
- manifest.toAbsolutePath().toString(),
- "-C",
- TestLambdaFormRetransformation.CP,
- Agent.class.getName() + ".class"
- };
-
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
-
- if (!jarTool.run(args)) {
- throw new Error("jar failed: args=" + Arrays.toString(args));
- }
- return jar;
- }
-
- private static Path createManifest() throws IOException {
- Path manifest = Files.createTempFile(Paths.get("."), null, ".mf");
- byte[] manifestBytes = TestLambdaFormRetransformation.MANIFEST.getBytes();
- Files.write(manifest, manifestBytes);
- return manifest;
- }
-}
-
-class Agent implements ClassFileTransformer {
- private static Runnable lambda = () -> {
- System.out.println("I'll crash you!");
- };
-
- public static void premain(String args, Instrumentation instrumentation) {
- if (!instrumentation.isRetransformClassesSupported()) {
- System.out.println("Class retransformation is not supported.");
- return;
- }
- System.out.println("Calling lambda to ensure that lambda forms were created");
-
- Agent.lambda.run();
-
- System.out.println("Registering class file transformer");
-
- instrumentation.addTransformer(new Agent());
-
- for (Class c : instrumentation.getAllLoadedClasses()) {
- if (c.getName().contains("LambdaForm") &&
- instrumentation.isModifiableClass(c)) {
- System.out.format("We've found a modifiable lambda form: %s%n", c.getName());
- try {
- instrumentation.retransformClasses(c);
- } catch (UnmodifiableClassException e) {
- throw new AssertionError("Modification of modifiable class " +
- "caused UnmodifiableClassException", e);
- }
- }
- }
- }
-
- public static void main(String args[]) {
- }
-
- @Override
- public byte[] transform(ClassLoader loader,
- String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain,
- byte[] classfileBuffer
- ) throws IllegalClassFormatException {
- System.out.println("Transforming " + className);
- return classfileBuffer.clone();
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/TestRedefineWithUnresolvedClass.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2014, 2017, 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 Redefine a class with an UnresolvedClass reference in the constant pool.
- * @bug 8035150
- * @library /test/lib
- * @modules java.base/jdk.internal.misc
- * java.compiler
- * java.instrument
- * java.management
- * jdk.jartool/sun.tools.jar
- * jdk.internal.jvmstat/sun.jvmstat.monitor
- * @build UnresolvedClassAgent
- * @run main TestRedefineWithUnresolvedClass
- */
-
-import java.io.File;
-import java.util.Arrays;
-
-import jdk.test.lib.process.OutputAnalyzer;
-import jdk.test.lib.process.ProcessTools;
-
-public class TestRedefineWithUnresolvedClass {
-
- final static String slash = File.separator;
- final static String testClasses = System.getProperty("test.classes") + slash;
-
- public static void main(String... args) throws Throwable {
- // delete this class to cause a NoClassDefFoundError
- File unresolved = new File(testClasses, "MyUnresolvedClass.class");
- if (unresolved.exists() && !unresolved.delete()) {
- throw new Exception("Could not delete: " + unresolved);
- }
-
- // build the javaagent
- buildJar("UnresolvedClassAgent");
-
- // launch a VM with the javaagent
- launchTest();
- }
-
- private static void buildJar(String jarName) throws Throwable {
- String testSrc = System.getProperty("test.src", "?") + slash;
-
- String jarPath = String.format("%s%s.jar", testClasses, jarName);
- String manifestPath = String.format("%s%s.mf", testSrc, jarName);
- String className = String.format("%s.class", jarName);
-
- String[] args = new String[] {"-cfm", jarPath, manifestPath, "-C", testClasses, className};
-
- System.out.println("Running jar " + Arrays.toString(args));
- sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
- if (!jarTool.run(args)) {
- throw new Exception("jar failed: args=" + Arrays.toString(args));
- }
- }
-
- private static void launchTest() throws Throwable {
- String[] args = {
- "-javaagent:" + testClasses + "UnresolvedClassAgent.jar",
- "-Dtest.classes=" + testClasses,
- "UnresolvedClassAgent" };
- OutputAnalyzer output = ProcessTools.executeTestJvm(args);
- output.shouldHaveExitValue(0);
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.java Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2014, 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.DataInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.lang.instrument.ClassDefinition;
-import java.lang.instrument.Instrumentation;
-
-/*
- * This class is present during compilation, but will be deleted before execution.
- */
-class MyUnresolvedClass {
- static void bar() {
- }
-}
-
-class MyRedefinedClass {
- static void foo() {
- MyUnresolvedClass.bar();
- }
-}
-
-public class UnresolvedClassAgent {
- public static void main(String... args) {
- }
-
- public static void premain(String args, Instrumentation inst) throws Exception {
- try {
- MyRedefinedClass.foo();
- } catch(NoClassDefFoundError err) {
- System.out.println("NoClassDefFoundError (expected)");
- }
-
- File f = new File(System.getProperty("test.classes"), "MyRedefinedClass.class");
- byte[] buf = new byte[(int)f.length()];
- try (DataInputStream dis = new DataInputStream(new FileInputStream(f))) {
- dis.readFully(buf);
- }
- ClassDefinition cd = new ClassDefinition(MyRedefinedClass.class, buf);
- inst.redefineClasses(new ClassDefinition[] {cd});
-
- try {
- MyRedefinedClass.foo();
- } catch(NoClassDefFoundError err) {
- System.out.println("NoClassDefFoundError (expected again)");
- }
- }
-}
--- a/test/hotspot/jtreg/serviceability/jvmti/UnresolvedClassAgent.mf Tue Mar 19 14:32:41 2019 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-Manifest-Version: 1.0
-Premain-Class: UnresolvedClassAgent
-Can-Redefine-Classes: true