< prev index next > test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java
Print this page
/*
! * Copyright (c) 2019, 2021, 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.
/*
! * Copyright (c) 2019, 2024, 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.
* questions.
*/
/*
* @test
! * @bug 8232613
- * @summary Ensure Object natives stay registered after redefinition
* @requires vm.jvmti
* @library /test/lib
! * @modules java.base/jdk.internal.misc
- * java.base/jdk.internal.org.objectweb.asm
- * java.compiler
- * java.instrument
* jdk.jartool/sun.tools.jar
* @run main RedefineObject buildagent
* @run main/othervm -javaagent:redefineagent.jar RedefineObject
*/
- import static jdk.test.lib.Asserts.assertTrue;
import jdk.test.lib.helpers.ClassFileInstaller;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
- import java.lang.RuntimeException;
import java.lang.instrument.ClassFileTransformer;
- import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;
- import java.util.Arrays;
-
- import jdk.internal.org.objectweb.asm.ClassReader;
- import jdk.internal.org.objectweb.asm.ClassVisitor;
- import jdk.internal.org.objectweb.asm.ClassWriter;
-
- import static jdk.internal.org.objectweb.asm.Opcodes.ASM6;
- import static jdk.internal.org.objectweb.asm.Opcodes.V1_8;
public class RedefineObject {
static Instrumentation inst;
public static void premain(String agentArgs, Instrumentation inst) {
RedefineObject.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);
! // Force an older ASM to force a bytecode update
- ClassVisitor cv = new DummyClassVisitor(ASM6, cw) { };
- ClassReader cr = new ClassReader(classfileBuffer);
- cr.accept(cv, 0);
- byte[] bytes = cw.toByteArray();
- return bytes;
- }
-
- public class DummyClassVisitor extends ClassVisitor {
-
- public DummyClassVisitor(int api, ClassVisitor cv) {
- super(api, cv);
- }
-
- public void visit(
- final int version,
- final int access,
- final String name,
- final String signature,
- final String superName,
- final String[] interfaces) {
- // Artificially lower to JDK 8 version to force a redefine
- cv.visit(V1_8, access, name, signature, superName, interfaces);
- }
- }
-
- @Override public byte[] transform(ClassLoader loader, String className,
- Class<?> classBeingRedefined,
- ProtectionDomain protectionDomain, byte[] classfileBuffer)
- throws IllegalClassFormatException {
-
if (className.contains("java/lang/Object")) {
! 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("RedefineObject");
} catch (Exception e) {
throw new RuntimeException("Could not write agent classfile", e);
}
! try {
- PrintWriter pw = new PrintWriter("MANIFEST.MF");
pw.println("Premain-Class: RedefineObject");
pw.println("Agent-Class: RedefineObject");
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");
* questions.
*/
/*
* @test
! * @summary Tests that java.lang.Object cannot be redefined/retransformed
* @requires vm.jvmti
* @library /test/lib
! * @modules java.instrument
* jdk.jartool/sun.tools.jar
* @run main RedefineObject buildagent
* @run main/othervm -javaagent:redefineagent.jar RedefineObject
*/
import jdk.test.lib.helpers.ClassFileInstaller;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.lang.instrument.UnmodifiableClassException;
import java.security.ProtectionDomain;
public class RedefineObject {
static Instrumentation inst;
public static void premain(String agentArgs, Instrumentation inst) {
RedefineObject.inst = inst;
}
static class Transformer implements ClassFileTransformer {
+ // set to true if transform method called to transform java.lang.Object
+ private boolean transformObjectInvoked;
! @Override
! public byte[] transform(ClassLoader loader,
! String className,
! Class<?> classBeingRedefined,
! ProtectionDomain protectionDomain,
! byte[] classfileBuffer) {
if (className.contains("java/lang/Object")) {
! transformObjectInvoked = true;
}
return null;
}
+
+ boolean transformObjectInvoked() {
+ return transformObjectInvoked;
+ }
}
private static void buildAgent() {
try {
ClassFileInstaller.main("RedefineObject");
} catch (Exception e) {
throw new RuntimeException("Could not write agent classfile", e);
}
! try (PrintWriter pw = new PrintWriter("MANIFEST.MF")) {
pw.println("Premain-Class: RedefineObject");
pw.println("Agent-Class: RedefineObject");
pw.println("Can-Retransform-Classes: true");
} 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");
throw new RuntimeException("Could not write the agent jar file");
}
}
public static void main(String[] args) throws Exception {
-
- int objHash = System.identityHashCode(Object.class);
- System.out.println("Object hashCode: " + objHash);
if (args.length == 1 && args[0].equals("buildagent")) {
buildAgent();
return;
}
if (inst == null) {
throw new RuntimeException("Instrumentation object was null");
}
try {
- inst.addTransformer(new RedefineObject.Transformer(), true);
inst.retransformClasses(Object.class);
} catch (UnmodifiableClassException e) {
! throw new RuntimeException(e);
}
!
! // Exercise native methods on Object after transform
- Object b = new Object();
- b.hashCode();
-
- C c = new C();
- assertTrue(c.hashCode() != c.clone().hashCode() || c != c.clone());
- assertTrue(c.clone() instanceof C);
- c = (C)c.clone(); // native method on new Object
- }
-
- private static class C implements Cloneable {
- @Override
- protected Object clone() throws CloneNotSupportedException {
- return super.clone();
}
}
}
throw new RuntimeException("Could not write the agent jar file");
}
}
public static void main(String[] args) throws Exception {
if (args.length == 1 && args[0].equals("buildagent")) {
buildAgent();
return;
}
if (inst == null) {
throw new RuntimeException("Instrumentation object was null");
}
+ if (inst.isModifiableClass(Object.class)) {
+ throw new RuntimeException("java.lang.Object should not be modifable");
+ }
+
+ var transformer = new Transformer();
+ inst.addTransformer(transformer, true);
try {
inst.retransformClasses(Object.class);
+ throw new RuntimeException("UnmodifiableClassException not thrown by retransformClasses");
} catch (UnmodifiableClassException e) {
! // expected
}
! if (transformer.transformObjectInvoked()) {
! throw new RuntimeException();
}
}
}
< prev index next >