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