/* * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /** * @test * @bug 4409241 4432820 * @summary Test the bug fix for: MethodExitEvents disappear when Object-Methods are called from main * @author Tim Bell * * @modules jdk.jdi * @run build TestScaffold VMConnection TargetListener TargetAdapter * @run compile -g MethodEntryExitEvents.java * @run driver MethodEntryExitEvents SUSPEND_EVENT_THREAD MethodEntryExitEventsDebugee * @run driver MethodEntryExitEvents SUSPEND_NONE MethodEntryExitEventsDebugee * @run driver MethodEntryExitEvents SUSPEND_ALL MethodEntryExitEventsDebugee */ import com.sun.jdi.*; import com.sun.jdi.event.*; import com.sun.jdi.request.*; import java.util.*; class t2 { public static void sayHello1(int i, int j) { sayHello2(i, j); } public static void sayHello2(int i, int j) { sayHello3(i, j); } public static void sayHello3(int i, int j) { sayHello4(i, j); } public static void sayHello4(int i, int j) { sayHello5(i, j); } public static void sayHello5(int i, int j) { if (i < 2) { sayHello1(++i, j); } else { System.out.print ("MethodEntryExitEventsDebugee: "); System.out.print (" -->> Hello. j is: "); System.out.print (j); System.out.println(" <<--"); } } } class MethodEntryExitEventsDebugee { public static void loopComplete () { /* * The implementation here is deliberately inefficient * because the debugger is still watching this method. */ StringBuffer sb = new StringBuffer(); sb.append ("MethodEntryExitEventsDebugee: "); sb.append ("Executing loopComplete method for a graceful shutdown..."); String s = sb.toString(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); System.out.print(c); } System.out.println(); } public static void main(String[] args) { t2 test = new t2(); for (int j = 0; j < 3; j++) { test.sayHello1(0, j); } loopComplete(); } } public class MethodEntryExitEvents extends TestScaffold { int sessionSuspendPolicy = EventRequest.SUSPEND_ALL; StepRequest stepReq = null; //Only one step request allowed per thread boolean finishedCounting = false; /* * Enter main() , then t2., then sayHello[1,2,3,4,5] 15 times 3 loops, * then loopComplete() */ final int expectedEntryCount = 1 + 1 + (15 * 3) + 1; int methodEntryCount = 0; /* * Exit t2., then sayHello[1,2,3,4,5] 15 times 3 loopa * (event monitoring is cancelled before we exit loopComplete() or main()) */ final int expectedExitCount = 1 + (15 * 3); int methodExitCount = 0; // Classes which we are interested in private List includes = Arrays.asList(new String[] { "MethodEntryExitEventsDebugee", "t2" }); MethodEntryExitEvents (String args[]) { super(args); } private void usage(String[] args) throws Exception { StringBuffer sb = new StringBuffer("Usage: "); sb.append(System.getProperty("line.separator")); sb.append(" java "); sb.append(getClass().getName()); sb.append(" [SUSPEND_NONE | SUSPEND_EVENT_THREAD | SUSPEND_ALL]"); sb.append(" [MethodEntryExitEventsDebugee | -connect ] "); throw new Exception (sb.toString()); } public static void main(String[] args) throws Exception { MethodEntryExitEvents meee = new MethodEntryExitEvents (args); meee.startTests(); } public void exceptionThrown(ExceptionEvent event) { System.out.println("Exception: " + event.exception()); System.out.println(" at catch location: " + event.catchLocation()); // Step to the catch if (stepReq == null) { stepReq = eventRequestManager().createStepRequest(event.thread(), StepRequest.STEP_MIN, StepRequest.STEP_INTO); stepReq.addCountFilter(1); // next step only stepReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); } stepReq.enable(); } public void stepCompleted(StepEvent event) { System.out.println("stepCompleted: line#=" + event.location().lineNumber() + " event=" + event); // disable the step and then run to completion //eventRequestManager().deleteEventRequest(event.request()); StepRequest str= (StepRequest)event.request(); str.disable(); } public void methodEntered(MethodEntryEvent event) { if (!includes.contains(event.method().declaringType().name())) { return; } if (! finishedCounting) { // We have to count the entry to loopComplete, but // not the exit methodEntryCount++; System.out.print (" Method entry number: "); System.out.print (methodEntryCount); System.out.print (" : "); System.out.println(event); if ("loopComplete".equals(event.method().name())) { finishedCounting = true; } } } public void methodExited(MethodExitEvent event) { if (!includes.contains(event.method().declaringType().name())) { return; } if (! finishedCounting){ methodExitCount++; System.out.print (" Method exit number: "); System.out.print (methodExitCount); System.out.print (" : "); System.out.println(event); } } protected void runTests() throws Exception { if (args.length < 1) { usage(args); } //Pick up the SUSPEND_xxx in first argument if ("SUSPEND_NONE".equals(args[0])) { sessionSuspendPolicy = EventRequest.SUSPEND_NONE; } else if ("SUSPEND_EVENT_THREAD".equals(args[0])) { sessionSuspendPolicy = EventRequest.SUSPEND_EVENT_THREAD; } else if ("SUSPEND_ALL".equals(args[0])) { sessionSuspendPolicy = EventRequest.SUSPEND_ALL; } else { usage(args); } System.out.print("Suspend policy is: "); System.out.println(args[0]); // Skip the test arg String[] args2 = new String[args.length - 1]; System.arraycopy(args, 1, args2, 0, args.length - 1); if (args2.length < 1) { usage(args2); } List argList = new ArrayList(Arrays.asList(args2)); System.out.println("run args: " + argList); connect((String[]) argList.toArray(args2)); waitForVMStart(); // Determine main thread ClassPrepareEvent e = resumeToPrepareOf("MethodEntryExitEventsDebugee"); mainThread = e.thread(); try { /* * Ask for Exception events */ ExceptionRequest exceptionRequest = eventRequestManager().createExceptionRequest(null, // refType (null == all instances) true, // notifyCaught true);// notifyUncaught exceptionRequest.addThreadFilter(mainThread); exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL); exceptionRequest.enable(); /* * Ask for method entry events */ MethodEntryRequest entryRequest = eventRequestManager().createMethodEntryRequest(); entryRequest.addThreadFilter(mainThread); entryRequest.setSuspendPolicy(sessionSuspendPolicy); entryRequest.enable(); /* * Ask for method exit events */ MethodExitRequest exitRequest = eventRequestManager().createMethodExitRequest(); exitRequest.addThreadFilter(mainThread); exitRequest.setSuspendPolicy(sessionSuspendPolicy); exitRequest.enable(); /* * We are now set up to receive the notifications we want. * Here we go. This adds 'this' as a listener so * that our handlers above will be called. */ listenUntilVMDisconnect(); System.out.println("All done..."); } catch (Exception ex){ ex.printStackTrace(); testFailed = true; } if ((methodEntryCount != expectedEntryCount) || (methodExitCount != expectedExitCount)) { testFailed = true; } if (!testFailed) { System.out.println(); System.out.println("MethodEntryExitEvents: passed"); System.out.print (" Method entry count: "); System.out.println(methodEntryCount); System.out.print (" Method exit count: "); System.out.println(methodExitCount); } else { System.out.println(); System.out.println("MethodEntryExitEvents: failed"); System.out.print (" expected method entry count: "); System.out.println(expectedEntryCount); System.out.print (" observed method entry count: "); System.out.println(methodEntryCount); System.out.print (" expected method exit count: "); System.out.println(expectedExitCount); System.out.print (" observed method exit count: "); System.out.println(methodExitCount); throw new Exception("MethodEntryExitEvents: failed"); } } }