1 /* 2 * Copyright (c) 2015, 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 8072008 27 * @library /testlibrary /../../test/lib 28 * @build RedefineTest Agent 29 * @run main ClassFileInstaller sun.hotspot.WhiteBox 30 * sun.hotspot.WhiteBox$WhiteBoxPermission 31 * java.lang.invoke.RedefineTest 32 * Agent 33 * jdk.test.lib.Asserts 34 * @run main Agent agent.jar java.lang.invoke.RedefineTest 35 * @run main/othervm -Xbootclasspath/a:. -javaagent:agent.jar 36 * -XX:+IgnoreUnrecognizedVMOptions 37 * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI 38 * -Xbatch -XX:-TieredCompilation -XX:CICompilerCount=1 39 * java.lang.invoke.RedefineTest 40 */ 41 package java.lang.invoke; 42 43 import sun.hotspot.WhiteBox; 44 import sun.misc.Unsafe; 45 46 import jdk.internal.org.objectweb.asm.*; 47 48 import java.lang.instrument.ClassDefinition; 49 import java.lang.instrument.Instrumentation; 50 51 import static jdk.internal.org.objectweb.asm.Opcodes.*; 52 53 public class RedefineTest { 54 static final MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP; 55 static final Unsafe UNSAFE = Unsafe.getUnsafe(); 56 57 static final String NAME = "java/lang/invoke/RedefineTest$T"; 58 59 static Class<?> getClass(int r) { 60 byte[] classFile = getClassFile(r); 61 return UNSAFE.defineClass(NAME, classFile, 0, classFile.length, null, null); 62 } 63 64 /** 65 * Generates a class of the following shape: 66 * static class T { 67 * @DontInline public static int f() { return $r; } 68 * } 69 */ 70 static byte[] getClassFile(int r) { 71 ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); 72 MethodVisitor mv; 73 cw.visit(52, ACC_PUBLIC | ACC_SUPER, NAME, null, "java/lang/Object", null); 74 { 75 mv = cw.visitMethod(ACC_PUBLIC | ACC_STATIC, "f", "()I", null, null); 76 mv.visitAnnotation("Ljava/lang/invoke/DontInline;", true); 77 mv.visitCode(); 78 mv.visitLdcInsn(r); 79 mv.visitInsn(IRETURN); 80 mv.visitMaxs(0, 0); 81 mv.visitEnd(); 82 } 83 cw.visitEnd(); 84 return cw.toByteArray(); 85 } 86 87 static final MethodHandle mh; 88 static final Class<?> CLS = getClass(0); 89 static { 90 try { 91 mh = LOOKUP.findStatic(CLS, "f", MethodType.methodType(int.class)); 92 } catch (Exception e) { 93 throw new Error(e); 94 } 95 } 96 97 static final WhiteBox WB = WhiteBox.getWhiteBox(); 98 99 @DontInline 100 static int invokeBasic() { 101 try { 102 return (int)mh.invokeExact(); 103 } catch (Throwable e) { 104 throw new Error(e); 105 } 106 } 107 108 static Instrumentation instr; 109 public static void premain(String args, Instrumentation instr) { 110 RedefineTest.instr = instr; 111 } 112 113 114 public static void main(String[] args) throws Exception { 115 for (int i = 0; i < 20_000; i++) { 116 int r = invokeBasic(); 117 if (r != 0) { 118 throw new Error(r + " != 0"); 119 } 120 } 121 // WB.ensureCompiled(); 122 123 redefine(); 124 125 int exp = (instr != null) ? 1 : 0; 126 127 for (int i = 0; i < 20_000; i++) { 128 if (invokeBasic() != exp) { 129 throw new Error(); 130 } 131 } 132 133 WB.clearInlineCaches(); 134 135 for (int i = 0; i < 20_000; i++) { 136 if (invokeBasic() != exp) { 137 throw new Error(); 138 } 139 } 140 141 // WB.ensureCompiled(); 142 } 143 144 static void redefine() { 145 if (instr == null) { 146 System.out.println("NOT REDEFINED"); 147 return; 148 } 149 ClassDefinition cd = new ClassDefinition(CLS, getClassFile(1)); 150 try { 151 instr.redefineClasses(cd); 152 } catch (Exception e) { 153 throw new Error(e); 154 } 155 System.out.println("REDEFINED"); 156 } 157 }