Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java
41153 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 823261326* @summary Ensure Object natives stay registered after redefinition27* @requires vm.jvmti28* @library /test/lib29* @modules java.base/jdk.internal.misc30* java.base/jdk.internal.org.objectweb.asm31* java.compiler32* java.instrument33* jdk.jartool/sun.tools.jar34* @run main RedefineObject buildagent35* @run main/othervm -javaagent:redefineagent.jar RedefineObject36*/3738import static jdk.test.lib.Asserts.assertTrue;39import jdk.test.lib.helpers.ClassFileInstaller;40import java.io.FileNotFoundException;41import java.io.PrintWriter;42import java.lang.RuntimeException;43import java.lang.instrument.ClassFileTransformer;44import java.lang.instrument.IllegalClassFormatException;45import java.lang.instrument.Instrumentation;46import java.lang.instrument.UnmodifiableClassException;47import java.security.ProtectionDomain;48import java.util.Arrays;4950import jdk.internal.org.objectweb.asm.ClassReader;51import jdk.internal.org.objectweb.asm.ClassVisitor;52import jdk.internal.org.objectweb.asm.ClassWriter;5354import static jdk.internal.org.objectweb.asm.Opcodes.ASM6;55import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;5657public class RedefineObject {5859static Instrumentation inst;6061public static void premain(String agentArgs, Instrumentation inst) {62RedefineObject.inst = inst;63}6465static class Transformer implements ClassFileTransformer {6667public byte[] asm(ClassLoader loader, String className,68Class<?> classBeingRedefined,69ProtectionDomain protectionDomain, byte[] classfileBuffer)70throws IllegalClassFormatException {71ClassWriter cw = new ClassWriter(0);72// Force an older ASM to force a bytecode update73ClassVisitor cv = new DummyClassVisitor(ASM6, cw) { };74ClassReader cr = new ClassReader(classfileBuffer);75cr.accept(cv, 0);76byte[] bytes = cw.toByteArray();77return bytes;78}7980public class DummyClassVisitor extends ClassVisitor {8182public DummyClassVisitor(int api, ClassVisitor cv) {83super(api, cv);84}8586public void visit(87final int version,88final int access,89final String name,90final String signature,91final String superName,92final String[] interfaces) {93// Artificially lower to JDK 8 version to force a redefine94cv.visit(V1_8, access, name, signature, superName, interfaces);95}96}9798@Override public byte[] transform(ClassLoader loader, String className,99Class<?> classBeingRedefined,100ProtectionDomain protectionDomain, byte[] classfileBuffer)101throws IllegalClassFormatException {102103if (className.contains("java/lang/Object")) {104try {105// Here we remove and re-add the dummy fields. This shuffles the constant pool106return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);107} catch (Throwable e) {108// The retransform native code that called this method does not propagate109// exceptions. Instead of getting an uninformative generic error, catch110// problems here and print it, then exit.111e.printStackTrace();112System.exit(1);113}114}115return null;116}117}118119private static void buildAgent() {120try {121ClassFileInstaller.main("RedefineObject");122} catch (Exception e) {123throw new RuntimeException("Could not write agent classfile", e);124}125126try {127PrintWriter pw = new PrintWriter("MANIFEST.MF");128pw.println("Premain-Class: RedefineObject");129pw.println("Agent-Class: RedefineObject");130pw.println("Can-Retransform-Classes: true");131pw.close();132} catch (FileNotFoundException e) {133throw new RuntimeException("Could not write manifest file for the agent", e);134}135136sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");137if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineObject.class" })) {138throw new RuntimeException("Could not write the agent jar file");139}140}141142public static void main(String[] args) throws Exception {143144int objHash = System.identityHashCode(Object.class);145System.out.println("Object hashCode: " + objHash);146if (args.length == 1 && args[0].equals("buildagent")) {147buildAgent();148return;149}150151if (inst == null) {152throw new RuntimeException("Instrumentation object was null");153}154155try {156inst.addTransformer(new RedefineObject.Transformer(), true);157inst.retransformClasses(Object.class);158} catch (UnmodifiableClassException e) {159throw new RuntimeException(e);160}161162// Exercise native methods on Object after transform163Object b = new Object();164b.hashCode();165166C c = new C();167assertTrue(c.hashCode() != c.clone().hashCode() || c != c.clone());168assertTrue(c.clone() instanceof C);169c = (C)c.clone(); // native method on new Object170}171172private static class C implements Cloneable {173@Override174protected Object clone() throws CloneNotSupportedException {175return super.clone();176}177}178}179180181