1 /* 2 * Copyright (c) 2001, 2002, 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 4287595 27 * @bug 4462989 28 * @bug 4531511 29 * @summary Test class redefinition 30 * 31 * @author Robert Field 32 * 33 * @library .. 34 * @run build TestScaffold VMConnection TargetListener TargetAdapter 35 * @run compile -g RedefineTest.java 36 * @run shell RedefineSetUp.sh 37 * @run driver RedefineTest 38 */ 39 import com.sun.jdi.*; 40 import com.sun.jdi.event.*; 41 import com.sun.jdi.request.*; 42 import java.util.*; 43 import java.io.*; 44 45 /********** target program **********/ 46 47 class RedefineTarg { 48 public static void show(String where){ 49 System.out.println("Returned: " + where); 50 } 51 52 public static void lastly(String where){ 53 } 54 55 public static void main(String[] args){ 56 RedefineSubTarg sub = new RedefineSubTarg(); 57 String where = ""; 58 for (int i = 0; i < 5; ++i) { 59 where = sub.foo(where); 60 show(where); 61 } 62 lastly(where); 63 } 64 } 65 66 /********** test program **********/ 67 68 public class RedefineTest extends TestScaffold { 69 ReferenceType targetClass; 70 static final String expected ="Boring Boring Different Boring Different "; 71 int repetitionCount = 0; 72 boolean beforeRedefine = true; 73 74 RedefineTest (String args[]) { 75 super(args); 76 } 77 78 public static void main(String[] args) throws Exception { 79 new RedefineTest(args).startTests(); 80 } 81 82 /********** event handlers **********/ 83 84 public void methodEntered(MethodEntryEvent event) { 85 Method meth = event.location().method(); 86 ThreadReference thread = event.thread(); 87 88 if (meth.name().equals("foo")) { 89 ++repetitionCount; 90 beforeRedefine = true; 91 try { 92 expectNonObsolete(thread); 93 inspectLineNumber(event, thread.frame(0)); 94 95 doRedefine(thread); 96 beforeRedefine = false; 97 98 switch (repetitionCount) { 99 case 1: 100 case 5: 101 expectNonObsolete(thread); 102 inspectLineNumber(event, thread.frame(0)); 103 break; 104 case 2: 105 case 3: 106 case 4: 107 expectObsolete(thread); 108 inspectLineNumber(event, thread.frame(0)); 109 break; 110 } 111 112 113 } catch (Exception exc) { 114 failure("Test Failure: unexpected exception - " + exc); 115 exc.printStackTrace(); 116 } 117 } 118 } 119 120 public void breakpointReached(BreakpointEvent event) { 121 ThreadReference thread = event.thread(); 122 try { 123 StackFrame frame = thread.frame(0); 124 LocalVariable lv = frame.visibleVariableByName("where"); 125 Value vWhere = frame.getValue(lv); 126 String remoteWhere = ((StringReference)vWhere).value(); 127 println("Value of where: " + remoteWhere); 128 if (!remoteWhere.equals(expected)) { 129 failure("FAIL: expected result string: '" + expected + 130 "' got: '" + remoteWhere + "'"); 131 } 132 } catch (Exception thr) { 133 failure("Test Failure: unexpected exception: " + thr); 134 } 135 } 136 137 /********** test assists **********/ 138 139 void expectNonObsolete(ThreadReference thread) throws Exception { 140 if (isObsolete(thread)) { 141 failure("FAIL: Method should NOT be obsolete"); 142 } else { 143 println("as it should be, not obsolete"); 144 } 145 } 146 147 void expectObsolete(ThreadReference thread) throws Exception { 148 if (isObsolete(thread)) { 149 println("obsolete like it should be"); 150 } else { 151 failure("FAIL: Method should be obsolete"); 152 } 153 } 154 155 void inspectLineNumber(LocatableEvent event, StackFrame frame) throws Exception { 156 /* 157 * For each value of repetitionCount, use the beforeRedefine 158 * boolean to distinguish the time before and after the actual 159 * redefinition takes place. Line numbers are inspected both 160 * before and after each redefine. 161 */ 162 int n = -1; 163 int expectedLine = -1; 164 switch (repetitionCount) { 165 case 1: 166 expectedLine = 4; 167 break; 168 case 2: 169 expectedLine = beforeRedefine ? 4:21; 170 break; 171 case 3: 172 expectedLine = beforeRedefine ? 21:4; 173 break; 174 case 4: 175 expectedLine = beforeRedefine ? 4:21; 176 break; 177 case 5: 178 /* The class won't be redefined on this iteration (look 179 * for a java.lang.UnsupportedOperationException instead) 180 * so expected line stays the same as last successful 181 * redefine. 182 */ 183 expectedLine = 21; 184 break; 185 } 186 Method method = event.location().method(); 187 if (frame.location().method().isObsolete()) { 188 /* 189 * Then skip. Obsolete methods are not interesting to 190 * inspect. 191 */ 192 println("inspectLineNumber skipping obsolete method " + method.name()); 193 } else { 194 n = method.location().lineNumber(); 195 int m = frame.location().lineNumber(); 196 if ((n != expectedLine) || (n != m)) { 197 failure("Test Failure: line number disagreement: " + 198 n + " (event) versus " + m + " (frame) versus " + expectedLine + 199 " (expected)"); 200 } else { 201 println("inspectLineNumber in method " + method.name() + " at line " + n); 202 } 203 } 204 } 205 206 boolean isObsolete(ThreadReference thread) throws Exception { 207 StackFrame frame = thread.frame(0); 208 Method meth = frame.location().method(); 209 return meth.isObsolete(); 210 } 211 212 void doRedefine(ThreadReference thread) throws Exception { 213 Exception receivedException = null; 214 String fileName = "notThis"; 215 216 switch (repetitionCount) { 217 case 1: 218 fileName = "RedefineSubTarg.class"; 219 break; 220 case 2: 221 fileName = "Different_RedefineSubTarg.class"; 222 break; 223 case 3: 224 fileName = "RedefineSubTarg.class"; 225 break; 226 case 4: 227 fileName = "Different_RedefineSubTarg.class"; 228 break; 229 case 5: 230 fileName = "SchemaChange_RedefineSubTarg.class"; 231 break; 232 } 233 File phyl = new File(fileName); 234 byte[] bytes = new byte[(int)phyl.length()]; 235 InputStream in = new FileInputStream(phyl); 236 in.read(bytes); 237 in.close(); 238 239 Map map = new HashMap(); 240 map.put(findReferenceType("RedefineSubTarg"), bytes); 241 242 println(System.getProperty("line.separator") + "Iteration # " + repetitionCount + 243 " ------ Redefine as: " + fileName); 244 try { 245 vm().redefineClasses(map); 246 } catch (Exception thr) { 247 receivedException = thr; 248 } 249 switch (repetitionCount) { 250 case 5: 251 if (receivedException == null) { 252 failure("FAIL: no exception; expected: UnsupportedOperationException"); 253 } else if (receivedException instanceof UnsupportedOperationException) { 254 println("Received expected exception: " + receivedException); 255 } else { 256 failure("FAIL: got exception: " + receivedException + 257 ", expected: UnsupportedOperationException"); 258 } 259 break; 260 default: 261 if (receivedException != null) { 262 failure("FAIL: unexpected exception: " + 263 receivedException); 264 } 265 break; 266 } 267 return; 268 } 269 270 /********** test core **********/ 271 272 protected void runTests() throws Exception { 273 274 BreakpointEvent bpe = startToMain("RedefineTarg"); 275 targetClass = bpe.location().declaringType(); 276 EventRequestManager erm = vm().eventRequestManager(); 277 278 /* 279 * Method entry in sub targ 280 */ 281 MethodEntryRequest mee = erm.createMethodEntryRequest(); 282 mee.addClassFilter("RedefineSubTarg"); 283 mee.enable(); 284 285 /* 286 * BP at end to get value 287 */ 288 List lastlys = targetClass.methodsByName("lastly"); 289 if (lastlys.size() != 1) { 290 throw new Exception ("TestFailure: Expected one 'lastly' method, found: " + 291 lastlys); 292 } 293 Location loc = ((Method)(lastlys.get(0))).location(); 294 EventRequest req = erm.createBreakpointRequest(loc); 295 req.enable(); 296 297 // Allow application to complete and shut down 298 listenUntilVMDisconnect(); 299 300 /* 301 * deal with results of test 302 * if anything has called failure("foo") testFailed will be true 303 */ 304 if (!testFailed) { 305 println("RedefineTest: passed"); 306 } else { 307 throw new Exception("RedefineTest: failed"); 308 } 309 } 310 }