Tue, 08 Apr 2014 09:51:25 +0200
8038636: speculative traps break when classes are redefined
Summary: remove speculative traps that point to methods that are redefined
Reviewed-by: kvn, twisti
1 /*
2 * Copyright (c) 2014, 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 */
24 import java.security.*;
25 import java.lang.instrument.*;
26 import java.lang.reflect.*;
27 import java.lang.management.ManagementFactory;
28 import com.sun.tools.attach.VirtualMachine;
30 class A {
31 void m() {
32 }
33 }
35 class B extends A {
36 void m() {
37 }
38 }
40 class C extends A {
41 void m() {
42 }
43 }
45 class Test {
47 static public void m() throws Exception {
48 for (int i = 0; i < 20000; i++) {
49 m1(a);
50 }
51 for (int i = 0; i < 4; i++) {
52 m1(b);
53 }
54 }
56 static boolean m1(A a) {
57 boolean res = Agent.m2(a);
58 return res;
59 }
61 static public A a = new A();
62 static public B b = new B();
63 static public C c = new C();
64 }
66 public class Agent implements ClassFileTransformer {
69 static class MemoryChunk {
70 MemoryChunk other;
71 long[] array;
72 MemoryChunk(MemoryChunk other) {
73 other = other;
74 array = new long[1024 * 1024 * 1024];
75 }
76 }
78 static public boolean m2(A a) {
79 boolean res = false;
80 if (a.getClass() == B.class) {
81 a.m();
82 } else {
83 res = true;
84 }
85 return res;
86 }
88 static public void main(String[] args) throws Exception {
89 // Create speculative trap entries
90 Test.m();
92 String nameOfRunningVM = ManagementFactory.getRuntimeMXBean().getName();
93 int p = nameOfRunningVM.indexOf('@');
94 String pid = nameOfRunningVM.substring(0, p);
96 // Make the nmethod go away
97 for (int i = 0; i < 10; i++) {
98 System.gc();
99 }
101 // Redefine class
102 try {
103 VirtualMachine vm = VirtualMachine.attach(pid);
104 vm.loadAgent(System.getProperty("test.classes",".") + "/agent.jar", "");
105 vm.detach();
106 } catch (Exception e) {
107 throw new RuntimeException(e);
108 }
110 Test.m();
111 // GC will hit dead method pointer
112 for (int i = 0; i < 10; i++) {
113 System.gc();
114 }
115 }
117 public synchronized byte[] transform(final ClassLoader classLoader,
118 final String className,
119 Class<?> classBeingRedefined,
120 ProtectionDomain protectionDomain,
121 byte[] classfileBuffer) {
122 System.out.println("Transforming class " + className);
123 return classfileBuffer;
124 }
126 public static void redefine(String agentArgs, Instrumentation instrumentation, Class to_redefine) {
128 try {
129 instrumentation.retransformClasses(to_redefine);
130 } catch (Exception e) {
131 e.printStackTrace();
132 }
134 }
136 public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Exception {
137 Agent transformer = new Agent();
138 instrumentation.addTransformer(transformer, true);
140 redefine(agentArgs, instrumentation, Test.class);
141 }
142 }