|
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 } |