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