1 /*
2 * Copyright (c) 2019, 2021, 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 * @bug 8232613
27 * @summary Ensure Object natives stay registered after redefinition
28 * @requires vm.jvmti
29 * @library /test/lib
30 * @modules java.base/jdk.internal.misc
31 * java.base/jdk.internal.org.objectweb.asm
32 * java.compiler
33 * java.instrument
34 * jdk.jartool/sun.tools.jar
35 * @run main RedefineObject buildagent
36 * @run main/othervm -javaagent:redefineagent.jar RedefineObject
37 */
38
39 import static jdk.test.lib.Asserts.assertTrue;
40 import jdk.test.lib.helpers.ClassFileInstaller;
41 import java.io.FileNotFoundException;
42 import java.io.PrintWriter;
43 import java.lang.RuntimeException;
44 import java.lang.instrument.ClassFileTransformer;
45 import java.lang.instrument.IllegalClassFormatException;
46 import java.lang.instrument.Instrumentation;
47 import java.lang.instrument.UnmodifiableClassException;
48 import java.security.ProtectionDomain;
49 import java.util.Arrays;
50
51 import jdk.internal.org.objectweb.asm.ClassReader;
52 import jdk.internal.org.objectweb.asm.ClassVisitor;
53 import jdk.internal.org.objectweb.asm.ClassWriter;
54
55 import static jdk.internal.org.objectweb.asm.Opcodes.ASM6;
56 import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;
57
58 public class RedefineObject {
59
60 static Instrumentation inst;
61
62 public static void premain(String agentArgs, Instrumentation inst) {
63 RedefineObject.inst = inst;
64 }
65
66 static class Transformer implements ClassFileTransformer {
67
68 public byte[] asm(ClassLoader loader, String className,
69 Class<?> classBeingRedefined,
70 ProtectionDomain protectionDomain, byte[] classfileBuffer)
71 throws IllegalClassFormatException {
72 ClassWriter cw = new ClassWriter(0);
73 // Force an older ASM to force a bytecode update
74 ClassVisitor cv = new DummyClassVisitor(ASM6, cw) { };
75 ClassReader cr = new ClassReader(classfileBuffer);
76 cr.accept(cv, 0);
77 byte[] bytes = cw.toByteArray();
78 return bytes;
79 }
80
81 public class DummyClassVisitor extends ClassVisitor {
82
83 public DummyClassVisitor(int api, ClassVisitor cv) {
84 super(api, cv);
85 }
86
87 public void visit(
88 final int version,
89 final int access,
90 final String name,
91 final String signature,
92 final String superName,
93 final String[] interfaces) {
94 // Artificially lower to JDK 8 version to force a redefine
95 cv.visit(V1_8, access, name, signature, superName, interfaces);
96 }
97 }
98
99 @Override public byte[] transform(ClassLoader loader, String className,
100 Class<?> classBeingRedefined,
101 ProtectionDomain protectionDomain, byte[] classfileBuffer)
102 throws IllegalClassFormatException {
103
104 if (className.contains("java/lang/Object")) {
105 try {
106 // Here we remove and re-add the dummy fields. This shuffles the constant pool
107 return asm(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
108 } catch (Throwable e) {
109 // The retransform native code that called this method does not propagate
110 // exceptions. Instead of getting an uninformative generic error, catch
111 // problems here and print it, then exit.
112 e.printStackTrace();
113 System.exit(1);
114 }
115 }
116 return null;
117 }
118 }
119
120 private static void buildAgent() {
121 try {
122 ClassFileInstaller.main("RedefineObject");
123 } catch (Exception e) {
124 throw new RuntimeException("Could not write agent classfile", e);
125 }
126
127 try {
128 PrintWriter pw = new PrintWriter("MANIFEST.MF");
129 pw.println("Premain-Class: RedefineObject");
130 pw.println("Agent-Class: RedefineObject");
131 pw.println("Can-Retransform-Classes: true");
132 pw.close();
133 } catch (FileNotFoundException e) {
134 throw new RuntimeException("Could not write manifest file for the agent", e);
135 }
136
137 sun.tools.jar.Main jarTool = new sun.tools.jar.Main(System.out, System.err, "jar");
138 if (!jarTool.run(new String[] { "-cmf", "MANIFEST.MF", "redefineagent.jar", "RedefineObject.class" })) {
139 throw new RuntimeException("Could not write the agent jar file");
140 }
141 }
142
143 public static void main(String[] args) throws Exception {
144
145 int objHash = System.identityHashCode(Object.class);
146 System.out.println("Object hashCode: " + objHash);
147 if (args.length == 1 && args[0].equals("buildagent")) {
148 buildAgent();
149 return;
150 }
151
152 if (inst == null) {
153 throw new RuntimeException("Instrumentation object was null");
154 }
155
156 try {
157 inst.addTransformer(new RedefineObject.Transformer(), true);
158 inst.retransformClasses(Object.class);
159 } catch (UnmodifiableClassException e) {
160 throw new RuntimeException(e);
161 }
162
163 // Exercise native methods on Object after transform
164 Object b = new Object();
165 b.hashCode();
166
167 C c = new C();
168 assertTrue(c.hashCode() != c.clone().hashCode() || c != c.clone());
169 assertTrue(c.clone() instanceof C);
170 c = (C)c.clone(); // native method on new Object
171 }
172
173 private static class C implements Cloneable {
174 @Override
175 protected Object clone() throws CloneNotSupportedException {
176 return super.clone();
177 }
178 }
179 }
|
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 }
|