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