MethodEntryExitEvents.java revision 6073:cea72c2bf071
1/* 2 * Copyright (c) 2001, 2012, 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 main MethodEntryExitEvents SUSPEND_EVENT_THREAD MethodEntryExitEventsDebugee 33 * @run main MethodEntryExitEvents SUSPEND_NONE MethodEntryExitEventsDebugee 34 * @run main MethodEntryExitEvents SUSPEND_ALL MethodEntryExitEventsDebugee 35 */ 36import com.sun.jdi.*; 37import com.sun.jdi.event.*; 38import com.sun.jdi.request.*; 39import java.util.*; 40 41class 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 66class 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 92public 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 /* 112 * Class patterns for which we don't want events (copied 113 * from the "Trace.java" example): 114 * http://java.sun.com/javase/technologies/core/toolsapis/jpda/ 115 */ 116 private String[] excludes = {"java.*", "javax.*", "sun.*", 117 "com.sun.*", "com.oracle.*", 118 "oracle.*"}; 119 120 MethodEntryExitEvents (String args[]) { 121 super(args); 122 } 123 124 private void usage(String[] args) throws Exception { 125 StringBuffer sb = new StringBuffer("Usage: "); 126 sb.append(System.getProperty("line.separator")); 127 sb.append(" java "); 128 sb.append(getClass().getName()); 129 sb.append(" [SUSPEND_NONE | SUSPEND_EVENT_THREAD | SUSPEND_ALL]"); 130 sb.append(" [MethodEntryExitEventsDebugee | -connect <connector options...>] "); 131 throw new Exception (sb.toString()); 132 } 133 134 public static void main(String[] args) throws Exception { 135 MethodEntryExitEvents meee = new MethodEntryExitEvents (args); 136 meee.startTests(); 137 } 138 139 public void exceptionThrown(ExceptionEvent event) { 140 System.out.println("Exception: " + event.exception()); 141 System.out.println(" at catch location: " + event.catchLocation()); 142 143 // Step to the catch 144 if (stepReq == null) { 145 stepReq = 146 eventRequestManager().createStepRequest(event.thread(), 147 StepRequest.STEP_MIN, 148 StepRequest.STEP_INTO); 149 stepReq.addCountFilter(1); // next step only 150 stepReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); 151 } 152 stepReq.enable(); 153 } 154 public void stepCompleted(StepEvent event) { 155 System.out.println("stepCompleted: line#=" + 156 event.location().lineNumber() + 157 " event=" + event); 158 // disable the step and then run to completion 159 //eventRequestManager().deleteEventRequest(event.request()); 160 StepRequest str= (StepRequest)event.request(); 161 str.disable(); 162 } 163 public void methodEntered(MethodEntryEvent event) { 164 if (! finishedCounting) { 165 // We have to count the entry to loopComplete, but 166 // not the exit 167 methodEntryCount++; 168 System.out.print (" Method entry number: "); 169 System.out.print (methodEntryCount); 170 System.out.print (" : "); 171 System.out.println(event); 172 if ("loopComplete".equals(event.method().name())) { 173 finishedCounting = true; 174 } 175 } 176 } 177 178 public void methodExited(MethodExitEvent event) { 179 if (! finishedCounting){ 180 methodExitCount++; 181 System.out.print (" Method exit number: "); 182 System.out.print (methodExitCount); 183 System.out.print (" : "); 184 System.out.println(event); 185 } 186 } 187 188 protected void runTests() throws Exception { 189 if (args.length < 1) { 190 usage(args); 191 } 192 //Pick up the SUSPEND_xxx in first argument 193 if ("SUSPEND_NONE".equals(args[0])) { 194 sessionSuspendPolicy = EventRequest.SUSPEND_NONE; 195 } else if ("SUSPEND_EVENT_THREAD".equals(args[0])) { 196 sessionSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD; 197 } else if ("SUSPEND_ALL".equals(args[0])) { 198 sessionSuspendPolicy = EventRequest.SUSPEND_ALL; 199 } else { 200 usage(args); 201 } 202 System.out.print("Suspend policy is: "); 203 System.out.println(args[0]); 204 205 // Skip the test arg 206 String[] args2 = new String[args.length - 1]; 207 System.arraycopy(args, 1, args2, 0, args.length - 1); 208 209 if (args2.length < 1) { 210 usage(args2); 211 } 212 List argList = new ArrayList(Arrays.asList(args2)); 213 System.out.println("run args: " + argList); 214 connect((String[]) argList.toArray(args2)); 215 waitForVMStart(); 216 217 try { 218 219 /* 220 * Ask for Exception events 221 */ 222 ExceptionRequest exceptionRequest = 223 eventRequestManager().createExceptionRequest(null, // refType (null == all instances) 224 true, // notifyCaught 225 true);// notifyUncaught 226 exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); 227 exceptionRequest.enable(); 228 229 /* 230 * Ask for method entry events 231 */ 232 MethodEntryRequest entryRequest = 233 eventRequestManager().createMethodEntryRequest(); 234 for (int i=0; i<excludes.length; ++i) { 235 entryRequest.addClassExclusionFilter(excludes[i]); 236 } 237 entryRequest.setSuspendPolicy(sessionSuspendPolicy); 238 entryRequest.enable(); 239 240 /* 241 * Ask for method exit events 242 */ 243 MethodExitRequest exitRequest = 244 eventRequestManager().createMethodExitRequest(); 245 246 for (int i=0; i<excludes.length; ++i) { 247 exitRequest.addClassExclusionFilter(excludes[i]); 248 } 249 exitRequest.setSuspendPolicy(sessionSuspendPolicy); 250 exitRequest.enable(); 251 252 /* 253 * We are now set up to receive the notifications we want. 254 * Here we go. This adds 'this' as a listener so 255 * that our handlers above will be called. 256 */ 257 258 listenUntilVMDisconnect(); 259 System.out.println("All done..."); 260 261 } catch (Exception ex){ 262 ex.printStackTrace(); 263 testFailed = true; 264 } 265 266 if ((methodEntryCount != expectedEntryCount) || 267 (methodExitCount != expectedExitCount)) { 268 testFailed = true; 269 } 270 if (!testFailed) { 271 System.out.println(); 272 System.out.println("MethodEntryExitEvents: passed"); 273 System.out.print (" Method entry count: "); 274 System.out.println(methodEntryCount); 275 System.out.print (" Method exit count: "); 276 System.out.println(methodExitCount); 277 } else { 278 System.out.println(); 279 System.out.println("MethodEntryExitEvents: failed"); 280 System.out.print (" expected method entry count: "); 281 System.out.println(expectedEntryCount); 282 System.out.print (" observed method entry count: "); 283 System.out.println(methodEntryCount); 284 System.out.print (" expected method exit count: "); 285 System.out.println(expectedExitCount); 286 System.out.print (" observed method exit count: "); 287 System.out.println(methodExitCount); 288 throw new Exception("MethodEntryExitEvents: failed"); 289 } 290 } 291} 292