1 /*
2  * Copyright (c) 2005, 2019, 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 6230699
27  * @summary Test ThreadReference.ownedMonitorsAndFrames()
28  * @bug 6701700
29  * @summary MonitorInfo objects aren't invalidated when the owning thread is resumed
30  * @author Swamy Venkataramanappa
31  *
32  * @run build TestScaffold VMConnection TargetListener TargetAdapter
33  * @run compile -g MonitorFrameInfo.java
34  * @run driver MonitorFrameInfo
35  */
36 import java.util.List;
37 
38 import com.sun.jdi.InvalidStackFrameException;
39 import com.sun.jdi.MonitorInfo;
40 import com.sun.jdi.ReferenceType;
41 import com.sun.jdi.ThreadReference;
42 import com.sun.jdi.event.BreakpointEvent;
43 
44     /********** target program **********/
45 
46 class MonitorFrameInfoTarg {
foo3()47     static void foo3() {
48         System.out.println("executing foo3");
49 
50     }
foo2()51     static void foo2() {
52         Object l1 = new Object();
53         synchronized(l1) {
54             System.out.println("executing foo2 " + l1);
55             foo3();
56         }
57     }
foo1()58     static void foo1() {
59         foo2();
60     }
main(String[] args)61     public static void main(String[] args){
62         System.out.println("Howdy!");
63         Object l1 = new Object();
64         synchronized(l1) {
65             System.out.println("executing main" + l1);
66             foo1();
67         }
68     }
69 }
70 
71     /********** test program **********/
72 
73 public class MonitorFrameInfo extends TestScaffold {
74     ReferenceType targetClass;
75     ThreadReference mainThread;
76     List<MonitorInfo> monitors;
77 
78     static int expectedCount = 2;
79     static int[] expectedDepth = { 1, 3 };
80 
81     static String[] expectedNames = {"foo3", "foo2", "foo1", "main"};
82 
MonitorFrameInfo(String args[])83     MonitorFrameInfo (String args[]) {
84         super(args);
85     }
86 
main(String[] args)87     public static void main(String[] args)      throws Exception {
88         new MonitorFrameInfo(args).startTests();
89     }
90 
91     /********** test core **********/
92 
runTests()93     protected void runTests() throws Exception {
94         /*
95          * Get to the top of main()
96          * to determine targetClass and mainThread
97          */
98         BreakpointEvent bpe = startToMain("MonitorFrameInfoTarg");
99         targetClass = bpe.location().declaringType();
100         mainThread = bpe.thread();
101 
102         int initialSize = mainThread.frames().size();
103 
104         resumeTo("MonitorFrameInfoTarg", "foo3", "()V");
105 
106         if (!mainThread.frame(0).location().method().name()
107                         .equals("foo3")) {
108             failure("FAILED: frame failed");
109         }
110 
111         if (mainThread.frames().size() != (initialSize + 3)) {
112             failure("FAILED: frames size failed");
113         }
114 
115         if (mainThread.frames().size() != mainThread.frameCount()) {
116             failure("FAILED: frames size not equal to frameCount");
117         }
118 
119         /* Test monitor frame info.
120          */
121         if (vm().canGetMonitorFrameInfo()) {
122             System.out.println("Get monitors");
123             monitors = mainThread.ownedMonitorsAndFrames();
124             if (monitors.size() != expectedCount) {
125                 failure("monitors count is not equal to expected count");
126             }
127             MonitorInfo mon = null;
128             for (int j=0; j < monitors.size(); j++) {
129                 mon  = (MonitorInfo)monitors.get(j);
130                 System.out.println("Monitor obj " + mon.monitor() + "depth =" +mon.stackDepth());
131                 if (mon.stackDepth() != expectedDepth[j]) {
132                     failure("FAILED: monitor stack depth is not equal to expected depth");
133                 }
134             }
135 
136             // The last gotten monInfo is in mon.   When we resume the thread,
137             // it should become invalid.  We will step out of the top frame
138             // so that the frame depth in this mon object will no longer be correct.
139             // That is why the monInfo's have to become invalid when the thread is
140             // resumed.
141             stepOut(mainThread);
142             boolean ok = false;
143             try {
144                 System.out.println("*** Saved Monitor obj " + mon.monitor() + "depth =" +mon.stackDepth());
145             } catch(InvalidStackFrameException ee) {
146                 // ok
147                 ok = true;
148                 System.out.println("Got expected InvalidStackFrameException after a resume");
149             }
150             if (!ok) {
151                 failure("FAILED: MonitorInfo object was not invalidated by a resume");
152             }
153         } else {
154             System.out.println("can not get monitors frame info");
155         }
156 
157 
158         /*
159          * resume until end
160          */
161         listenUntilVMDisconnect();
162 
163         /*
164          * deal with results of test
165          * if anything has called failure("foo") testFailed will be true
166          */
167         if (!testFailed) {
168             println("MonitorFrameInfo: passed");
169         } else {
170             throw new Exception("MonitorFrameInfo: failed");
171         }
172     }
173 }
174