1 /*
  2  * Copyright (c) 2007, 2020, 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  *
 27  * @summary converted from VM Testbase nsk/jdi/ObjectReference/referringObjects/referringObjects003.
 28  * VM Testbase keywords: [quick, jpda, jdi, feature_jdk6_jpda, vm6]
 29  * VM Testbase readme:
 30  * DESCRIPTION
 31  *     Test check behaviour of ObjectReference.referringObjects for ThreadReference and ThreadGroupReference
 32  *     and ObjectReference.disableCollection/ObjectReference.enableCollection for ThreadGroupReference
 33  *     The test scenario is following:
 34  *       - Debugger VM
 35  *         - initiate in target VM thread execution:
 36  *                 - Debugee VM
 37  *                 - start several threads included in thread group
 38  *                 - create references of all possible types to all started threads and thread group
 39  *       - Debugger VM
 40  *         - check that threads and thread group have correct number of referrers:
 41  *         (thread referrers should include thread group and references with supported types,
 42  *          thread group referrers should include group's threads, parent thread group and references with supported types)
 43  *       - Debugger VM
 44  *         - initiate in target VM thread stop:
 45  *         - Debugee VM
 46  *             - stop all threads and remove all references to threads and thread group
 47  *       - Debugger VM
 48  *         - check that thread group have only 1 referrer: parent thread group
 49  *         - check that threre are no references to test threads in target VM
 50  *       - Debugger VM
 51  *         - test ObjectReference.disableCollection, ObjectReference.enableCollection for ThreadGroupReference:
 52  *         can't force collection of thread group because of thread group always has 1 referrer - parent thread group, so
 53  *         just test disableCollection/enableCollection don't throw any unexpected exceptions
 54  *
 55  * @requires !vm.graal.enabled
 56  * @library /vmTestbase
 57  *          /test/lib
 58  * @build nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003
 59  *        nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a
 60  * @run main/othervm/native
 61  *      nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003
 62  *      -verbose
 63  *      -arch=${os.family}-${os.simpleArch}
 64  *      -waittime=5
 65  *      -debugee.vmkind=java
 66  *      -transport.address=dynamic
 67  *      -debugee.vmkeys="-Xmx256M ${test.vm.opts} ${test.java.opts}"
 68  */
 69 
 70 package nsk.jdi.ObjectReference.referringObjects.referringObjects003;
 71 
 72 import java.io.PrintStream;
 73 import java.util.*;
 74 import com.sun.jdi.*;
 75 import nsk.share.Consts;
 76 import nsk.share.jdi.HeapwalkingDebuggee;
 77 import nsk.share.jdi.HeapwalkingDebugger;
 78 import nsk.share.jpda.AbstractDebuggeeTest;
 79 
 80 public class referringObjects003 extends HeapwalkingDebugger {
 81 
 82     public static void main(String argv[]) {
 83         System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
 84     }
 85 
 86     public static int run(String argv[], PrintStream out) {
 87         return new referringObjects003().runIt(argv, out);
 88     }
 89 
 90     protected String debuggeeClassName() {
 91         return "nsk.jdi.ObjectReference.referringObjects.referringObjects003.referringObjects003a";
 92     }
 93 
 94     // check ObjectReference type and number of referrers
 95     public void checkThreadGroupReferrersCount(List<ObjectReference> objectReferences, int expectedCount) {
 96         for (ObjectReference objectReference : objectReferences) {
 97             if (!(objectReference instanceof ThreadGroupReference)) {
 98                 setSuccess(false);
 99                 log.complain("Unexpected type of ObjectReference: " + objectReference.getClass().getName()
100                         + ", expected ThreadGroupReference");
101             }
102 
103             int referrerCount = objectReference.referringObjects(0).size();
104 
105             if (referrerCount != expectedCount) {
106                 setSuccess(false);
107                 log
108                         .complain("List with wrong size was returned by ObjectReference.referringObjects(ThreadGroupReference): "
109                                 + referrerCount + ", expected: " + expectedCount);
110             }
111         }
112     }
113 
114     // check ObjectReference type and number of referrers
115     public void checkThreadReferrersCount(List<ObjectReference> objectReferences, int expectedCount) {
116         for (ObjectReference objectReference : objectReferences) {
117             if (!(objectReference instanceof ThreadReference)) {
118                 setSuccess(false);
119                 log.complain("Unexpected type of ObjectReference: " + objectReference.getClass().getName()
120                         + ", expected ThreadReference");
121             }
122 
123             if (((ThreadReference)objectReference).name().contains("Test thread") == false)
124                 continue;
125 
126             int referrerCount = objectReference.referringObjects(0).size();
127 
128             if (referrerCount != expectedCount) {
129                 setSuccess(false);
130                 log.complain("List with wrong size was returned by ObjectReference.referringObjects(ThreadReferrence): "
131                              + referrerCount + ", expected: " + expectedCount);
132             }
133         }
134     }
135 
136     public void doTest() {
137         int threadCount = 15;
138 
139         // threads and thread groups loaded before debugger command should be
140         // filtered
141         List<ObjectReference> threadGroupsToFilter = HeapwalkingDebugger.getObjectReferences(
142                 "java.lang.ThreadGroup",
143                 vm);
144         List<ObjectReference> threadsToFilter = HeapwalkingDebugger.getObjectReferences("java.lang.Thread", vm);
145 
146         pipe.println(referringObjects003a.COMMAND_START_THREADS + ":" + threadCount);
147 
148         if (!isDebuggeeReady())
149             return;
150 
151         // check instance count
152         checkDebugeeAnswer_instances("java.lang.ThreadGroup", threadGroupsToFilter.size() + 1);
153         checkDebugeeAnswer_instances("java.lang.Thread", threadsToFilter.size() + threadCount);
154 
155         List<ObjectReference> threadGroups = HeapwalkingDebugger.filterObjectReferrence(
156                 threadGroupsToFilter,
157                 HeapwalkingDebugger.getObjectReferences("java.lang.ThreadGroup", vm));
158 
159         // thread group has 'threadCount' referrers + 1 referrer is parent
160         // thread group
161         // + 'includedIntoReferrersCountTypes.size()' referrers was additionally
162         // created
163         int expectedCount = threadCount + 1 + HeapwalkingDebuggee.includedIntoReferrersCountTypes.size();
164 
165         checkThreadGroupReferrersCount(threadGroups, expectedCount);
166 
167         List<ObjectReference> threads = HeapwalkingDebugger.filterObjectReferrence(threadsToFilter, HeapwalkingDebugger
168                 .getObjectReferences("java.lang.Thread", vm));
169 
170         expectedCount = 2 + HeapwalkingDebuggee.includedIntoReferrersCountTypes.size();
171 
172         // 1 referrer is debugee object + 1 referrer is thread group
173         // + 'includedIntoReferrersCountTypes.size()' referrers was additionally
174         // created
175         checkThreadReferrersCount(threads, expectedCount);
176 
177         pipe.println(referringObjects003a.COMMAND_STOP_THREADS);
178 
179         if (!isDebuggeeReady())
180             return;
181 
182         checkDebugeeAnswer_instances("java.lang.ThreadGroup", threadGroupsToFilter.size() + 1);
183         checkDebugeeAnswer_instances("java.lang.Thread", threadsToFilter.size());
184 
185         threadGroups = HeapwalkingDebugger.filterObjectReferrence(threadGroupsToFilter, HeapwalkingDebugger
186                 .getObjectReferences("java.lang.ThreadGroup", vm));
187 
188         // 1 referrer(parent thread group) is left
189         checkThreadGroupReferrersCount(threadGroups, 1);
190 
191         threads = HeapwalkingDebugger.filterObjectReferrence(threadsToFilter, HeapwalkingDebugger.getObjectReferences(
192                 "java.lang.Thread",
193                 vm));
194 
195         if (threads.size() != 0) {
196             log.complain("All test threads should be removed");
197             log.complain("Unexpected threads:");
198             for (ObjectReference objectReference : threads) {
199                 log.complain(objectReference.toString());
200             }
201         }
202 
203         checkThreadGroupDisableCollection(threadGroups);
204     }
205 
206     // can't force collection of thread group because of 1 reference is always
207     // left in parent tread group
208     public void checkThreadGroupDisableCollection(List<ObjectReference> objectReferences) {
209         try {
210             for (ObjectReference objectReference : objectReferences)
211                 objectReference.disableCollection();
212         } catch (Throwable t) {
213             log.complain("Unexpected exception: " + t);
214             t.printStackTrace(log.getOutStream());
215         }
216 
217         forceGC();
218         try {
219             for (ObjectReference objectReference : objectReferences)
220                 objectReference.enableCollection();
221         } catch (Throwable t) {
222             log.complain("Unexpected exception: " + t);
223             t.printStackTrace(log.getOutStream());
224         }
225 
226         forceGC();
227         try {
228             for (ObjectReference objectReference : objectReferences)
229                 objectReference.referringObjects(0);
230         } catch (Throwable t) {
231             log.complain("Unexpected exception: " + t);
232             t.printStackTrace(log.getOutStream());
233         }
234     }
235 }