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.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package java.lang.management;
  27 
  28 import javax.management.openmbean.CompositeData;
  29 import sun.management.MonitorInfoCompositeData;
  30 
  31 /**
  32  * Information about an object monitor lock.  An object monitor is locked
  33  * when entering a synchronization block or method on that object.
  34  *
  35  * <h2>MXBean Mapping</h2>
  36  * {@code MonitorInfo} is mapped to a {@link CompositeData CompositeData}
  37  * with attributes as specified in
  38  * the {@link #from from} method.
  39  *
  40  * @author  Mandy Chung
  41  * @since   1.6
  42  */
  43 public class MonitorInfo extends LockInfo {
  44 
  45     private int    stackDepth;
  46     private StackTraceElement stackFrame;
  47 
  48     /**
  49      * Construct a {@code MonitorInfo} object.
  50      *
  51      * @param className the fully qualified name of the class of the lock object.
  52      * @param identityHashCode the {@link System#identityHashCode
  53      *                         identity hash code} of the lock object.
  54      * @param stackDepth the depth in the stack trace where the object monitor
  55      *                   was locked.
  56      * @param stackFrame the stack frame that locked the object monitor.
  57      * @throws IllegalArgumentException if
  58      *    {@code stackDepth} &ge; 0 but {@code stackFrame} is {@code null},
  59      *    or {@code stackDepth} &lt; 0 but {@code stackFrame} is not
  60      *       {@code null}.
  61      */
  62     public MonitorInfo(String className,
  63                        int identityHashCode,
  64                        int stackDepth,
  65                        StackTraceElement stackFrame) {
  66         super(className, identityHashCode);
  67         if (stackDepth >= 0 && stackFrame == null) {
  68             throw new IllegalArgumentException("Parameter stackDepth is " +
  69                 stackDepth + " but stackFrame is null");
  70         }
  71         if (stackDepth < 0 && stackFrame != null) {
  72             throw new IllegalArgumentException("Parameter stackDepth is " +
  73                 stackDepth + " but stackFrame is not null");
  74         }
  75         this.stackDepth = stackDepth;
  76         this.stackFrame = stackFrame;
  77     }
  78 
  79     /**
  80      * Returns the depth in the stack trace where the object monitor
  81      * was locked.  The depth is the index to the {@code StackTraceElement}
  82      * array returned in the {@link ThreadInfo#getStackTrace} method.
  83      *
  84      * @return the depth in the stack trace where the object monitor
  85      *         was locked, or a negative number if not available.
  86      */
  87     public int getLockedStackDepth() {
  88         return stackDepth;
  89     }
  90 
  91     /**
  92      * Returns the stack frame that locked the object monitor.
  93      *
  94      * @return {@code StackTraceElement} that locked the object monitor,
  95      *         or {@code null} if not available.
  96      */
  97     public StackTraceElement getLockedStackFrame() {
  98         return stackFrame;
  99     }
 100 
 101     /**
 102      * Returns a {@code MonitorInfo} object represented by the
 103      * given {@code CompositeData}.
 104      * The given {@code CompositeData} must contain the following attributes
 105      * as well as the attributes specified in the
 106      * <a href="LockInfo.html#MappedType">
 107      * mapped type</a> for the {@link LockInfo} class:
 108      * <table class="striped" style="margin-left:2em">
 109      * <caption style="display:none">The attributes and their types the given CompositeData contains</caption>
 110      * <thead>
 111      * <tr>
 112      *   <th scope="col">Attribute Name</th>
 113      *   <th scope="col">Type</th>
 114      * </tr>
 115      * </thead>
 116      * <tbody style="text-align:left">
 117      * <tr>
 118      *   <th scope="row">lockedStackFrame</th>
 119      *   <td><a href="ThreadInfo.html#stackTraceElement">
 120      *       {@code CompositeData} for {@code StackTraceElement}</a> as specified
 121      *       in {@link ThreadInfo#from(CompositeData)} method.
 122      *   </td>
 123      * </tr>
 124      * <tr>
 125      *   <th scope="row">lockedStackDepth</th>
 126      *   <td>{@code java.lang.Integer}</td>
 127      * </tr>
 128      * </tbody>
 129      * </table>
 130      *
 131      * @param cd {@code CompositeData} representing a {@code MonitorInfo}
 132      *
 133      * @throws IllegalArgumentException if {@code cd} does not
 134      *   represent a {@code MonitorInfo} with the attributes described
 135      *   above.
 136      *
 137      * @return a {@code MonitorInfo} object represented
 138      *         by {@code cd} if {@code cd} is not {@code null};
 139      *         {@code null} otherwise.
 140      */
 141     public static MonitorInfo from(CompositeData cd) {
 142         if (cd == null) {
 143             return null;
 144         }
 145 
 146         if (cd instanceof MonitorInfoCompositeData) {
 147             return ((MonitorInfoCompositeData) cd).getMonitorInfo();
 148         } else {
 149             MonitorInfoCompositeData.validateCompositeData(cd);
 150             String className = MonitorInfoCompositeData.getClassName(cd);
 151             int identityHashCode = MonitorInfoCompositeData.getIdentityHashCode(cd);
 152             int stackDepth = MonitorInfoCompositeData.getLockedStackDepth(cd);
 153             StackTraceElement stackFrame = MonitorInfoCompositeData.getLockedStackFrame(cd);
 154             return new MonitorInfo(className,
 155                                    identityHashCode,
 156                                    stackDepth,
 157                                    stackFrame);
 158         }
 159     }
 160 
 161 }