1 /* 2 * Copyright (c) 2001, 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 4409241 4432820 27 * @summary Test the bug fix for: MethodExitEvents disappear when Object-Methods are called from main 28 * @author Tim Bell 29 * 30 * @run build TestScaffold VMConnection TargetListener TargetAdapter 31 * @run compile -g MethodEntryExitEvents.java 32 * @run driver MethodEntryExitEvents SUSPEND_EVENT_THREAD MethodEntryExitEventsDebugee 33 * @run driver MethodEntryExitEvents SUSPEND_NONE MethodEntryExitEventsDebugee 34 * @run driver MethodEntryExitEvents SUSPEND_ALL MethodEntryExitEventsDebugee 35 */ 36 import com.sun.jdi.*; 37 import com.sun.jdi.event.*; 38 import com.sun.jdi.request.*; 39 import java.util.*; 40 41 class t2 { 42 public static void sayHello1(int i, int j) { 43 sayHello2(i, j); 44 } 45 public static void sayHello2(int i, int j) { 46 sayHello3(i, j); 47 } 48 public static void sayHello3(int i, int j) { 49 sayHello4(i, j); 50 } 51 public static void sayHello4(int i, int j) { 52 sayHello5(i, j); 53 } 54 public static void sayHello5(int i, int j) { 55 if (i < 2) { 56 sayHello1(++i, j); 57 } else { 58 System.out.print ("MethodEntryExitEventsDebugee: "); 59 System.out.print (" -->> Hello. j is: "); 60 System.out.print (j); 61 System.out.println(" <<--"); 62 } 63 } 64 } 65 66 class MethodEntryExitEventsDebugee { 67 public static void loopComplete () { 68 /* 69 * The implementation here is deliberately inefficient 70 * because the debugger is still watching this method. 71 */ 72 StringBuffer sb = new StringBuffer(); 73 sb.append ("MethodEntryExitEventsDebugee: "); 74 sb.append ("Executing loopComplete method for a graceful shutdown..."); 75 String s = sb.toString(); 76 for (int i = 0; i < s.length(); i++) { 77 char c = s.charAt(i); 78 System.out.print(c); 79 } 80 System.out.println(); 81 } 82 public static void main(String[] args) { 83 t2 test = new t2(); 84 for (int j = 0; j < 3; j++) { 85 test.sayHello1(0, j); 86 } 87 loopComplete(); 88 } 89 } 90 91 92 public class MethodEntryExitEvents extends TestScaffold { 93 int sessionSuspendPolicy = EventRequest.SUSPEND_ALL; 94 StepRequest stepReq = null; //Only one step request allowed per thread 95 boolean finishedCounting = false; 96 97 /* 98 * Enter main() , then t2.<init>, then sayHello[1,2,3,4,5] 15 times 3 loops, 99 * then loopComplete() 100 */ 101 final int expectedEntryCount = 1 + 1 + (15 * 3) + 1; 102 int methodEntryCount = 0; 103 104 /* 105 * Exit t2.<init>, then sayHello[1,2,3,4,5] 15 times 3 loopa 106 * (event monitoring is cancelled before we exit loopComplete() or main()) 107 */ 108 final int expectedExitCount = 1 + (15 * 3); 109 int methodExitCount = 0; 110 111 // Classes which we are interested in 112 private List includes = Arrays.asList(new String[] { 113 "MethodEntryExitEventsDebugee", 114 "t2" 115 }); 116 117 MethodEntryExitEvents (String args[]) { 118 super(args); 119 } 120 121 private void usage(String[] args) throws Exception { 122 StringBuffer sb = new StringBuffer("Usage: "); 123 sb.append(System.getProperty("line.separator")); 124 sb.append(" java "); 125 sb.append(getClass().getName()); 126 sb.append(" [SUSPEND_NONE | SUSPEND_EVENT_THREAD | SUSPEND_ALL]"); 127 sb.append(" [MethodEntryExitEventsDebugee | -connect <connector options...>] "); 128 throw new Exception (sb.toString()); 129 } 130 131 public static void main(String[] args) throws Exception { 132 MethodEntryExitEvents meee = new MethodEntryExitEvents (args); 133 meee.startTests(); 134 } 135 136 public void exceptionThrown(ExceptionEvent event) { 137 System.out.println("Exception: " + event.exception()); 138 System.out.println(" at catch location: " + event.catchLocation()); 139 140 // Step to the catch 141 if (stepReq == null) { 142 stepReq = 143 eventRequestManager().createStepRequest(event.thread(), 144 StepRequest.STEP_MIN, 145 StepRequest.STEP_INTO); 146 stepReq.addCountFilter(1); // next step only 147 stepReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); 148 } 149 stepReq.enable(); 150 } 151 public void stepCompleted(StepEvent event) { 152 System.out.println("stepCompleted: line#=" + 153 event.location().lineNumber() + 154 " event=" + event); 155 // disable the step and then run to completion 156 //eventRequestManager().deleteEventRequest(event.request()); 157 StepRequest str= (StepRequest)event.request(); 158 str.disable(); 159 } 160 public void methodEntered(MethodEntryEvent event) { 161 if (!includes.contains(event.method().declaringType().name())) { 162 return; 163 } 164 165 if (! finishedCounting) { 166 // We have to count the entry to loopComplete, but 167 // not the exit 168 methodEntryCount++; 169 System.out.print (" Method entry number: "); 170 System.out.print (methodEntryCount); 171 System.out.print (" : "); 172 System.out.println(event); 173 if ("loopComplete".equals(event.method().name())) { 174 finishedCounting = true; 175 } 176 } 177 } 178 179 public void methodExited(MethodExitEvent event) { 180 if (!includes.contains(event.method().declaringType().name())) { 181 return; 182 } 183 184 if (! finishedCounting){ 185 methodExitCount++; 186 System.out.print (" Method exit number: "); 187 System.out.print (methodExitCount); 188 System.out.print (" : "); 189 System.out.println(event); 190 } 191 } 192 193 protected void runTests() throws Exception { 194 if (args.length < 1) { 195 usage(args); 196 } 197 //Pick up the SUSPEND_xxx in first argument 198 if ("SUSPEND_NONE".equals(args[0])) { 199 sessionSuspendPolicy = EventRequest.SUSPEND_NONE; 200 } else if ("SUSPEND_EVENT_THREAD".equals(args[0])) { 201 sessionSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD; 202 } else if ("SUSPEND_ALL".equals(args[0])) { 203 sessionSuspendPolicy = EventRequest.SUSPEND_ALL; 204 } else { 205 usage(args); 206 } 207 System.out.print("Suspend policy is: "); 208 System.out.println(args[0]); 209 210 // Skip the test arg 211 String[] args2 = new String[args.length - 1]; 212 System.arraycopy(args, 1, args2, 0, args.length - 1); 213 214 if (args2.length < 1) { 215 usage(args2); 216 } 217 List argList = new ArrayList(Arrays.asList(args2)); 218 System.out.println("run args: " + argList); 219 connect((String[]) argList.toArray(args2)); 220 waitForVMStart(); 221 222 // Determine main thread 223 ClassPrepareEvent e = resumeToPrepareOf("MethodEntryExitEventsDebugee"); 224 mainThread = e.thread(); 225 226 try { 227 228 /* 229 * Ask for Exception events 230 */ 231 ExceptionRequest exceptionRequest = 232 eventRequestManager().createExceptionRequest(null, // refType (null == all instances) 233 true, // notifyCaught 234 true);// notifyUncaught 235 exceptionRequest.addThreadFilter(mainThread); 236 exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); 237 exceptionRequest.enable(); 238 239 /* 240 * Ask for method entry events 241 */ 242 MethodEntryRequest entryRequest = 243 eventRequestManager().createMethodEntryRequest(); 244 entryRequest.addThreadFilter(mainThread); 245 entryRequest.setSuspendPolicy(sessionSuspendPolicy); 246 entryRequest.enable(); 247 248 /* 249 * Ask for method exit events 250 */ 251 MethodExitRequest exitRequest = 252 eventRequestManager().createMethodExitRequest(); 253 exitRequest.addThreadFilter(mainThread); 254 exitRequest.setSuspendPolicy(sessionSuspendPolicy); 255 exitRequest.enable(); 256 257 /* 258 * We are now set up to receive the notifications we want. 259 * Here we go. This adds 'this' as a listener so 260 * that our handlers above will be called. 261 */ 262 263 listenUntilVMDisconnect(); 264 System.out.println("All done..."); 265 266 } catch (Exception ex){ 267 ex.printStackTrace(); 268 testFailed = true; 269 } 270 271 if ((methodEntryCount != expectedEntryCount) || 272 (methodExitCount != expectedExitCount)) { 273 testFailed = true; 274 } 275 if (!testFailed) { 276 System.out.println(); 277 System.out.println("MethodEntryExitEvents: passed"); 278 System.out.print (" Method entry count: "); 279 System.out.println(methodEntryCount); 280 System.out.print (" Method exit count: "); 281 System.out.println(methodExitCount); 282 } else { 283 System.out.println(); 284 System.out.println("MethodEntryExitEvents: failed"); 285 System.out.print (" expected method entry count: "); 286 System.out.println(expectedEntryCount); 287 System.out.print (" observed method entry count: "); 288 System.out.println(methodEntryCount); 289 System.out.print (" expected method exit count: "); 290 System.out.println(expectedExitCount); 291 System.out.print (" observed method exit count: "); 292 System.out.println(methodExitCount); 293 throw new Exception("MethodEntryExitEvents: failed"); 294 } 295 } 296 }