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