1 /* 2 * Copyright (c) 2002, 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 4628726 27 * @summary Test class redefinition - method data line numbers and local vars, 28 * @author Robert Field 29 * 30 * @library .. 31 * 32 * @run build TestScaffold VMConnection TargetListener TargetAdapter 33 * @run compile -g RedefineTest.java 34 * @run shell RedefineSetUp.sh 35 * @run driver RedefineTest -repeat 3 36 * @run driver RedefineTest 37 */ 38 import com.sun.jdi.*; 39 import com.sun.jdi.event.*; 40 import com.sun.jdi.request.*; 41 import java.util.*; 42 import java.io.*; 43 44 /********** target program **********/ 45 46 class RedefineTarg { 47 public static void main(String[] args){ 48 RedefineSubTarg.stemcp(); 49 RedefineSubTarg sub = new RedefineSubTarg(); 50 sub.bottom(); 51 RedefineSubTarg.stnemcp(); 52 RedefineSubTarg.stemcp(); 53 } 54 } 55 56 /********** test program **********/ 57 58 public class RedefineTest extends TestScaffold { 59 static int redefineRepeat = 1; 60 int bpCnt = 0; 61 62 // isObsolete, linenumber, lv name, lv value, lv isArg 63 String[] before = { 64 "+ 3", 65 "+ 6 eights 888 T", 66 "+ 11 rot 4 F", 67 "+ 15", 68 "+ 20 myArg 56 T paramy 12 F", 69 "+ 24", 70 "+ 28", 71 "+ 33" }; 72 String[] after = { 73 "+ 5", 74 "O", 75 "O", 76 "+ 16", 77 "+ 21 whoseArg 56 T parawham 12 F", 78 "+ 25", 79 "O", 80 "+ 34" }; 81 String[] shorter = { 82 "+ 5", 83 "+ 9 eights 88 T", 84 "+ 13", 85 "+ 16", 86 "+ 21 whoseArg 56 T parawham 12 F", 87 "+ 25" }; 88 String[] refresh = { 89 "+ 5", 90 "+ 9 eights 88 T", 91 "+ 13", 92 "+ 16", 93 "+ 21 whoseArg 56 T parawham 12 F", 94 "+ 25", 95 "+ 29", 96 "+ 34" }; 97 int[] bps = {7, 12, 16, 21, 25, 30, 34}; 98 String[][] bpPlaces = { 99 {"+ 16"}, 100 {"+ 21 myArg 56 T paramy 12 F"}, 101 {"+ 25"}, 102 {"+ 34"} }; 103 104 static String[] processArgs(String args[]) { 105 if (args.length > 0 && args[0].equals("-repeat")) { 106 redefineRepeat = Integer.decode(args[1]).intValue(); 107 String[] args2 = new String[args.length - 2]; 108 System.arraycopy(args, 2, args2, 0, args.length - 2); 109 return args2; 110 } else { 111 return args; 112 } 113 } 114 115 RedefineTest (String args[]) { 116 super(args); 117 } 118 119 public static void main(String[] args) throws Exception { 120 new RedefineTest(processArgs(args)).startTests(); 121 } 122 123 124 /********** event handlers **********/ 125 126 public void breakpointReached(BreakpointEvent event) { 127 println("Got BreakpointEvent - " + event); 128 try { 129 checkFrames(event.thread(), bpPlaces[bpCnt++]); 130 if (bpCnt >= bpPlaces.length) { 131 eventRequestManager().deleteAllBreakpoints(); 132 } 133 } catch (Exception exc) { 134 failure("FAIL: breakpoint checking threw " + exc); 135 } 136 } 137 138 /********** test assists **********/ 139 140 // isObsolete, linenumber, lv name, lv value, lv isArg 141 // equals: ref type (always), method (not obsolete) 142 void checkFrames(ThreadReference thread, String[] matchList) throws Exception { 143 for (int i = 0; i < matchList.length; ++i) { 144 String match = matchList[i]; 145 StackFrame frame = thread.frame(i); 146 Location loc = frame.location(); 147 ReferenceType refType = loc.declaringType(); 148 Method meth = loc.method(); 149 String errInfo = "\nframe " + i + ": " + loc + "\n match: " + match; 150 if (!findReferenceType("RedefineSubTarg").equals(refType)) { 151 failure("FAIL: Bad reference type - " + errInfo); 152 return; // might be bad class, but might have run past bottom 153 } 154 StringTokenizer st = new StringTokenizer(match); 155 boolean expectObs = st.nextToken().equals("O"); 156 println("Frame " + i + ": " + meth); 157 if (meth.isObsolete()) { 158 if (!expectObs) { 159 failure("FAIL: Method should NOT be obsolete - " + errInfo); 160 } 161 } else { 162 if (expectObs) { 163 failure("FAIL: Method should be obsolete - " + errInfo); 164 break; // no more data to read 165 } 166 if (!findMethod(refType, meth.name(), meth.signature()).equals(meth)) { 167 failure("FAIL: Non matching method - " + errInfo); 168 } 169 int line = loc.lineNumber(); 170 if (line != Integer.parseInt(st.nextToken())) { 171 failure("FAIL: Unexpected line number: " + errInfo); 172 } 173 // local var matching 174 int lvCnt = 0; 175 while (st.hasMoreTokens()) { 176 ++lvCnt; 177 String lvName = st.nextToken(); 178 int lvValue = Integer.parseInt(st.nextToken()); 179 boolean isArg = st.nextToken().equals("T"); 180 LocalVariable lv = frame.visibleVariableByName(lvName); 181 if (lv == null) { 182 failure("FAIL: local var not found: '" + lvName + 183 "' -- " + errInfo); 184 } else { 185 Value val = frame.getValue(lv); 186 int ival = ((IntegerValue)val).value(); 187 if (ival != lvValue) { 188 failure("FAIL: expected value: '" + lvValue + 189 "' got: '" + ival + "' -- " + errInfo); 190 } 191 if (lv.isArgument() != isArg) { 192 failure("FAIL: expected argument: '" + isArg + 193 "' got: '" + lv.isArgument() + "' -- " + errInfo); 194 } 195 } 196 } 197 List locals = frame.visibleVariables(); 198 if (locals.size() != lvCnt) { 199 failure("FAIL: expected '" + lvCnt + 200 "' locals were '" + locals.size() + 201 "' -- " + errInfo + "' -- " + locals); 202 } 203 } 204 } 205 } 206 207 208 void doRedefine(String fileName) throws Exception { 209 File phyl = new File(fileName); 210 byte[] bytes = new byte[(int)phyl.length()]; 211 InputStream in = new FileInputStream(phyl); 212 in.read(bytes); 213 in.close(); 214 215 Map map = new HashMap(); 216 map.put(findReferenceType("RedefineSubTarg"), bytes); 217 218 try { 219 for (int i = 0; i < redefineRepeat; ++i) { 220 vm().redefineClasses(map); 221 } 222 } catch (Exception thr) { 223 failure("FAIL: unexpected exception: " + thr); 224 } 225 } 226 227 ThreadReference toTop() { 228 BreakpointEvent bpe = resumeTo("RedefineSubTarg", "top", "()V"); 229 return bpe.thread(); 230 } 231 232 void setBP(int line) { 233 try { 234 Location loc = findLocation(findReferenceType("RedefineSubTarg"), line); 235 final BreakpointRequest request = 236 eventRequestManager().createBreakpointRequest(loc); 237 request.enable(); 238 } catch (Exception exc) { 239 failure("FAIL: Attempt to set BP at line " + line + " threw " + exc); 240 } 241 } 242 243 /********** test core **********/ 244 245 protected void runTests() throws Exception { 246 247 startToMain("RedefineTarg"); 248 249 ThreadReference thread = toTop(); 250 251 println("------ Before Redefine ------"); 252 checkFrames(thread, before); 253 254 println("------ After Redefine ------"); 255 doRedefine("Different_RedefineSubTarg.class"); 256 checkFrames(thread, after); 257 258 println("------ Static 2 ------"); 259 toTop(); 260 checkFrames(thread, shorter); 261 262 println("------ Instance ------"); 263 toTop(); 264 checkFrames(thread, shorter); 265 266 println("------ Re-entered ------"); 267 toTop(); 268 checkFrames(thread, refresh); 269 270 println("------ Breakpoints ------"); 271 doRedefine("RedefineSubTarg.class"); 272 for (int i = 0; i < bps.length; ++i) { 273 setBP(bps[i]); 274 } 275 276 /* 277 * resume the target listening for events 278 */ 279 listenUntilVMDisconnect(); 280 281 if (bpCnt != bpPlaces.length) { 282 failure("FAIL: Wrong number of breakpoints encountered: " + bpCnt); 283 } 284 285 /* 286 * deal with results of test 287 * if anything has called failure("foo") testFailed will be true 288 */ 289 if (!testFailed) { 290 println("RedefineTest(method): passed"); 291 } else { 292 throw new Exception("RedefineTest(method): failed"); 293 } 294 } 295 }