1 /* 2 * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* 25 * @test 26 * @summary Tests that java.lang.Object cannot be redefined/retransformed 27 * @requires vm.jvmti 28 * @library /test/lib 29 * @modules java.instrument 30 * jdk.jartool/sun.tools.jar 31 * @run main RedefineObject buildagent 32 * @run main/othervm -javaagent:redefineagent.jar RedefineObject 33 */ 34 35 import jdk.test.lib.helpers.ClassFileInstaller; 36 import java.io.FileNotFoundException; 37 import java.io.PrintWriter; 38 import java.lang.instrument.ClassFileTransformer; 39 import java.lang.instrument.Instrumentation; 40 import java.lang.instrument.UnmodifiableClassException; 41 import java.security.ProtectionDomain; 42 43 public class RedefineObject { 44 45 static Instrumentation inst; 46 47 public static void premain(String agentArgs, Instrumentation inst) { 48 RedefineObject.inst = inst; 49 } 50 51 static class Transformer implements ClassFileTransformer { 52 // set to true if transform method called to transform java.lang.Object 53 private boolean transformObjectInvoked; 54 55 @Override 56 public byte[] transform(ClassLoader loader, 57 String className, 58 Class<?> classBeingRedefined, 59 ProtectionDomain protectionDomain, 60 byte[] classfileBuffer) { 61 if (className.contains("java/lang/Object")) { 62 transformObjectInvoked = true; 63 } 64 return null; 65 } 66 67 boolean transformObjectInvoked() { 68 return transformObjectInvoked; 69 } 70 } 71 72 private static void buildAgent() { 73 try { 74 ClassFileInstaller.main("RedefineObject"); 75 } catch (Exception e) { 76 throw new RuntimeException("Could not write agent classfile", e); 77 } 78 79 try (PrintWriter pw = new PrintWriter("MANIFEST.MF")) { 80 pw.println("Premain-Class: RedefineObject"); 81 pw.println("Agent-Class: RedefineObject"); 82 pw.println("Can-Retransform-Classes: true"); 83 } catch (FileNotFoundException e) { 84 throw new RuntimeException("Could not write manifest file for the agent", e); 85 } 86 87 sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar"); 88 if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineObject.class" })) { 89 throw new RuntimeException("Could not write the agent jar file"); 90 } 91 } 92 93 public static void main(String[] args) throws Exception { 94 if (args.length == 1 && args[0].equals("buildagent")) { 95 buildAgent(); 96 return; 97 } 98 99 if (inst == null) { 100 throw new RuntimeException("Instrumentation object was null"); 101 } 102 103 if (inst.isModifiableClass(Object.class)) { 104 throw new RuntimeException("java.lang.Object should not be modifable"); 105 } 106 107 var transformer = new Transformer(); 108 inst.addTransformer(transformer, true); 109 try { 110 inst.retransformClasses(Object.class); 111 throw new RuntimeException("UnmodifiableClassException not thrown by retransformClasses"); 112 } catch (UnmodifiableClassException e) { 113 // expected 114 } 115 if (transformer.transformObjectInvoked()) { 116 throw new RuntimeException(); 117 } 118 } 119 }