src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java
changeset 47216 71c04702a3d5
parent 36511 9d0388c6b336
child 49077 b1c42b3cd19b
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2004, 2012, 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 sun.management;
       
    27 
       
    28 import java.lang.management.ThreadInfo;
       
    29 import java.lang.management.MonitorInfo;
       
    30 import java.lang.management.LockInfo;
       
    31 import javax.management.openmbean.CompositeType;
       
    32 import javax.management.openmbean.CompositeData;
       
    33 import javax.management.openmbean.CompositeDataSupport;
       
    34 import javax.management.openmbean.OpenDataException;
       
    35 
       
    36 /**
       
    37  * A CompositeData for ThreadInfo for the local management support.
       
    38  * This class avoids the performance penalty paid to the
       
    39  * construction of a CompositeData use in the local case.
       
    40  */
       
    41 public class ThreadInfoCompositeData extends LazyCompositeData {
       
    42     private final ThreadInfo threadInfo;
       
    43     private final CompositeData cdata;
       
    44     private final boolean currentVersion;
       
    45     private final boolean hasV6;
       
    46 
       
    47     private ThreadInfoCompositeData(ThreadInfo ti) {
       
    48         this.threadInfo = ti;
       
    49         this.currentVersion = true;
       
    50         this.cdata = null;
       
    51         this.hasV6 = true;
       
    52     }
       
    53 
       
    54     private ThreadInfoCompositeData(CompositeData cd) {
       
    55         this.threadInfo = null;
       
    56         this.currentVersion = ThreadInfoCompositeData.isCurrentVersion(cd);
       
    57         this.cdata = cd;
       
    58         this.hasV6 = ThreadInfoCompositeData.hasV6(cd);
       
    59     }
       
    60 
       
    61     public ThreadInfo getThreadInfo() {
       
    62         return threadInfo;
       
    63     }
       
    64 
       
    65     public boolean hasV6() {
       
    66         return hasV6;
       
    67     }
       
    68 
       
    69     public boolean isCurrentVersion() {
       
    70         return currentVersion;
       
    71     }
       
    72 
       
    73     public static ThreadInfoCompositeData getInstance(CompositeData cd) {
       
    74         validateCompositeData(cd);
       
    75         return new ThreadInfoCompositeData(cd);
       
    76     }
       
    77 
       
    78     public static CompositeData toCompositeData(ThreadInfo ti) {
       
    79         ThreadInfoCompositeData ticd = new ThreadInfoCompositeData(ti);
       
    80         return ticd.getCompositeData();
       
    81     }
       
    82 
       
    83     protected CompositeData getCompositeData() {
       
    84         // Convert StackTraceElement[] to CompositeData[]
       
    85         StackTraceElement[] stackTrace = threadInfo.getStackTrace();
       
    86         CompositeData[] stackTraceData =
       
    87             new CompositeData[stackTrace.length];
       
    88         for (int i = 0; i < stackTrace.length; i++) {
       
    89             StackTraceElement ste = stackTrace[i];
       
    90             stackTraceData[i] = StackTraceElementCompositeData.toCompositeData(ste);
       
    91         }
       
    92 
       
    93         // Convert MonitorInfo[] and LockInfo[] to CompositeData[]
       
    94         CompositeData lockInfoData =
       
    95             LockInfoCompositeData.toCompositeData(threadInfo.getLockInfo());
       
    96 
       
    97         // Convert LockInfo[] and MonitorInfo[] to CompositeData[]
       
    98         LockInfo[] lockedSyncs = threadInfo.getLockedSynchronizers();
       
    99         CompositeData[] lockedSyncsData =
       
   100             new CompositeData[lockedSyncs.length];
       
   101         for (int i = 0; i < lockedSyncs.length; i++) {
       
   102             LockInfo li = lockedSyncs[i];
       
   103             lockedSyncsData[i] = LockInfoCompositeData.toCompositeData(li);
       
   104         }
       
   105 
       
   106         MonitorInfo[] lockedMonitors = threadInfo.getLockedMonitors();
       
   107         CompositeData[] lockedMonitorsData =
       
   108             new CompositeData[lockedMonitors.length];
       
   109         for (int i = 0; i < lockedMonitors.length; i++) {
       
   110             MonitorInfo mi = lockedMonitors[i];
       
   111             lockedMonitorsData[i] = MonitorInfoCompositeData.toCompositeData(mi);
       
   112         }
       
   113 
       
   114         // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
       
   115         // threadInfoItemNames!
       
   116         final Object[] threadInfoItemValues = {
       
   117             threadInfo.getThreadId(),
       
   118             threadInfo.getThreadName(),
       
   119             threadInfo.getThreadState().name(),
       
   120             threadInfo.getBlockedTime(),
       
   121             threadInfo.getBlockedCount(),
       
   122             threadInfo.getWaitedTime(),
       
   123             threadInfo.getWaitedCount(),
       
   124             lockInfoData,
       
   125             threadInfo.getLockName(),
       
   126             threadInfo.getLockOwnerId(),
       
   127             threadInfo.getLockOwnerName(),
       
   128             stackTraceData,
       
   129                 threadInfo.isSuspended(),
       
   130                 threadInfo.isInNative(),
       
   131             lockedMonitorsData,
       
   132             lockedSyncsData,
       
   133             threadInfo.isDaemon(),
       
   134             threadInfo.getPriority(),
       
   135         };
       
   136 
       
   137         try {
       
   138             return new CompositeDataSupport(threadInfoCompositeType,
       
   139                                             threadInfoItemNames,
       
   140                                             threadInfoItemValues);
       
   141         } catch (OpenDataException e) {
       
   142             // Should never reach here
       
   143             throw new AssertionError(e);
       
   144         }
       
   145     }
       
   146 
       
   147     // Attribute names
       
   148     private static final String THREAD_ID       = "threadId";
       
   149     private static final String THREAD_NAME     = "threadName";
       
   150     private static final String THREAD_STATE    = "threadState";
       
   151     private static final String BLOCKED_TIME    = "blockedTime";
       
   152     private static final String BLOCKED_COUNT   = "blockedCount";
       
   153     private static final String WAITED_TIME     = "waitedTime";
       
   154     private static final String WAITED_COUNT    = "waitedCount";
       
   155     private static final String LOCK_INFO       = "lockInfo";
       
   156     private static final String LOCK_NAME       = "lockName";
       
   157     private static final String LOCK_OWNER_ID   = "lockOwnerId";
       
   158     private static final String LOCK_OWNER_NAME = "lockOwnerName";
       
   159     private static final String STACK_TRACE     = "stackTrace";
       
   160     private static final String SUSPENDED       = "suspended";
       
   161     private static final String IN_NATIVE       = "inNative";
       
   162     private static final String DAEMON          = "daemon";
       
   163     private static final String PRIORITY        = "priority";
       
   164     private static final String LOCKED_MONITORS = "lockedMonitors";
       
   165     private static final String LOCKED_SYNCS    = "lockedSynchronizers";
       
   166 
       
   167     private static final String[] threadInfoItemNames = {
       
   168         THREAD_ID,
       
   169         THREAD_NAME,
       
   170         THREAD_STATE,
       
   171         BLOCKED_TIME,
       
   172         BLOCKED_COUNT,
       
   173         WAITED_TIME,
       
   174         WAITED_COUNT,
       
   175         LOCK_INFO,
       
   176         LOCK_NAME,
       
   177         LOCK_OWNER_ID,
       
   178         LOCK_OWNER_NAME,
       
   179         STACK_TRACE,
       
   180         SUSPENDED,
       
   181         IN_NATIVE,
       
   182         LOCKED_MONITORS,
       
   183         LOCKED_SYNCS,
       
   184         DAEMON,
       
   185         PRIORITY,
       
   186     };
       
   187 
       
   188     // New attributes added in 6.0 ThreadInfo
       
   189     private static final String[] threadInfoV6Attributes = {
       
   190         LOCK_INFO,
       
   191         LOCKED_MONITORS,
       
   192         LOCKED_SYNCS,
       
   193     };
       
   194 
       
   195     private static final String[] threadInfoV9Attributes = {
       
   196         DAEMON,
       
   197         PRIORITY,
       
   198     };
       
   199 
       
   200     // Current version of ThreadInfo
       
   201     private static final CompositeType threadInfoCompositeType;
       
   202     // Previous version of ThreadInfo
       
   203     private static final CompositeType threadInfoV6CompositeType;
       
   204     // Previous-previous version of ThreadInfo
       
   205     private static final CompositeType threadInfoV5CompositeType;
       
   206     private static final CompositeType lockInfoCompositeType;
       
   207     static {
       
   208         try {
       
   209             threadInfoCompositeType = (CompositeType)
       
   210                 MappedMXBeanType.toOpenType(ThreadInfo.class);
       
   211             // Form a CompositeType for JDK 5.0 ThreadInfo version
       
   212 
       
   213             threadInfoV5CompositeType =
       
   214                 TypeVersionMapper.getInstance().getVersionedCompositeType(
       
   215                     threadInfoCompositeType, TypeVersionMapper.V5
       
   216                 );
       
   217 
       
   218             threadInfoV6CompositeType =
       
   219                 TypeVersionMapper.getInstance().getVersionedCompositeType(
       
   220                     threadInfoCompositeType, TypeVersionMapper.V6
       
   221                 );
       
   222         } catch (OpenDataException e) {
       
   223             // Should never reach here
       
   224             throw new AssertionError(e);
       
   225         }
       
   226 
       
   227         // Each CompositeData object has its CompositeType associated
       
   228         // with it.  So we can get the CompositeType representing LockInfo
       
   229         // from a mapped CompositeData for any LockInfo object.
       
   230         // Thus we construct a random LockInfo object and pass it
       
   231         // to LockInfoCompositeData to do the conversion.
       
   232         Object o = new Object();
       
   233         LockInfo li = new LockInfo(o.getClass().getName(),
       
   234                                    System.identityHashCode(o));
       
   235         CompositeData cd = LockInfoCompositeData.toCompositeData(li);
       
   236         lockInfoCompositeType = cd.getCompositeType();
       
   237     }
       
   238 
       
   239     static boolean isV5Attribute(String itemName) {
       
   240         for (String n : threadInfoV6Attributes) {
       
   241             if (itemName.equals(n)) {
       
   242                 return false;
       
   243             }
       
   244         }
       
   245         for (String n : threadInfoV9Attributes) {
       
   246             if (itemName.equals(n)) {
       
   247                 return false;
       
   248             }
       
   249         }
       
   250         return true;
       
   251     }
       
   252 
       
   253     static boolean isV6Attribute(String itemName) {
       
   254         for (String n : threadInfoV9Attributes) {
       
   255             if (itemName.equals(n)) {
       
   256                 return false;
       
   257             }
       
   258         }
       
   259         return true;
       
   260     }
       
   261 
       
   262     public static boolean isCurrentVersion(CompositeData cd) {
       
   263         if (cd == null) {
       
   264             throw new NullPointerException("Null CompositeData");
       
   265         }
       
   266 
       
   267         return isTypeMatched(threadInfoCompositeType, cd.getCompositeType());
       
   268     }
       
   269 
       
   270     private static boolean hasV6(CompositeData cd) {
       
   271         if (cd == null) {
       
   272             throw new NullPointerException("Null CompositeData");
       
   273         }
       
   274 
       
   275         return isTypeMatched(threadInfoCompositeType, cd.getCompositeType()) ||
       
   276                isTypeMatched(threadInfoV6CompositeType, cd.getCompositeType());
       
   277      }
       
   278 
       
   279     public long threadId() {
       
   280         return getLong(cdata, THREAD_ID);
       
   281     }
       
   282 
       
   283     public String threadName() {
       
   284         // The ThreadName item cannot be null so we check that
       
   285         // it is present with a non-null value.
       
   286         String name = getString(cdata, THREAD_NAME);
       
   287         if (name == null) {
       
   288             throw new IllegalArgumentException("Invalid composite data: " +
       
   289                 "Attribute " + THREAD_NAME + " has null value");
       
   290         }
       
   291         return name;
       
   292     }
       
   293 
       
   294     public Thread.State threadState() {
       
   295         return Thread.State.valueOf(getString(cdata, THREAD_STATE));
       
   296     }
       
   297 
       
   298     public long blockedTime() {
       
   299         return getLong(cdata, BLOCKED_TIME);
       
   300     }
       
   301 
       
   302     public long blockedCount() {
       
   303         return getLong(cdata, BLOCKED_COUNT);
       
   304     }
       
   305 
       
   306     public long waitedTime() {
       
   307         return getLong(cdata, WAITED_TIME);
       
   308     }
       
   309 
       
   310     public long waitedCount() {
       
   311         return getLong(cdata, WAITED_COUNT);
       
   312     }
       
   313 
       
   314     public String lockName() {
       
   315         // The LockName and LockOwnerName can legitimately be null,
       
   316         // we don't bother to check the value
       
   317         return getString(cdata, LOCK_NAME);
       
   318     }
       
   319 
       
   320     public long lockOwnerId() {
       
   321         return getLong(cdata, LOCK_OWNER_ID);
       
   322     }
       
   323 
       
   324     public String lockOwnerName() {
       
   325         return getString(cdata, LOCK_OWNER_NAME);
       
   326     }
       
   327 
       
   328     public boolean suspended() {
       
   329         return getBoolean(cdata, SUSPENDED);
       
   330     }
       
   331 
       
   332     public boolean inNative() {
       
   333         return getBoolean(cdata, IN_NATIVE);
       
   334     }
       
   335 
       
   336     public boolean isDaemon() {
       
   337         return getBoolean(cdata, DAEMON);
       
   338     }
       
   339 
       
   340     public int getPriority(){
       
   341         return getInt(cdata, PRIORITY);
       
   342     }
       
   343 
       
   344     public StackTraceElement[] stackTrace() {
       
   345         CompositeData[] stackTraceData =
       
   346             (CompositeData[]) cdata.get(STACK_TRACE);
       
   347 
       
   348         // The StackTrace item cannot be null, but if it is we will get
       
   349         // a NullPointerException when we ask for its length.
       
   350         StackTraceElement[] stackTrace =
       
   351             new StackTraceElement[stackTraceData.length];
       
   352         for (int i = 0; i < stackTraceData.length; i++) {
       
   353             CompositeData cdi = stackTraceData[i];
       
   354             stackTrace[i] = StackTraceElementCompositeData.from(cdi);
       
   355         }
       
   356         return stackTrace;
       
   357     }
       
   358 
       
   359     // 6.0 new attributes
       
   360     public LockInfo lockInfo() {
       
   361         CompositeData lockInfoData = (CompositeData) cdata.get(LOCK_INFO);
       
   362         return LockInfo.from(lockInfoData);
       
   363     }
       
   364 
       
   365     public MonitorInfo[] lockedMonitors() {
       
   366         CompositeData[] lockedMonitorsData =
       
   367             (CompositeData[]) cdata.get(LOCKED_MONITORS);
       
   368 
       
   369         // The LockedMonitors item cannot be null, but if it is we will get
       
   370         // a NullPointerException when we ask for its length.
       
   371         MonitorInfo[] monitors =
       
   372             new MonitorInfo[lockedMonitorsData.length];
       
   373         for (int i = 0; i < lockedMonitorsData.length; i++) {
       
   374             CompositeData cdi = lockedMonitorsData[i];
       
   375             monitors[i] = MonitorInfo.from(cdi);
       
   376         }
       
   377         return monitors;
       
   378     }
       
   379 
       
   380     public LockInfo[] lockedSynchronizers() {
       
   381         CompositeData[] lockedSyncsData =
       
   382             (CompositeData[]) cdata.get(LOCKED_SYNCS);
       
   383 
       
   384         // The LockedSynchronizers item cannot be null, but if it is we will
       
   385         // get a NullPointerException when we ask for its length.
       
   386         LockInfo[] locks = new LockInfo[lockedSyncsData.length];
       
   387         for (int i = 0; i < lockedSyncsData.length; i++) {
       
   388             CompositeData cdi = lockedSyncsData[i];
       
   389             locks[i] = LockInfo.from(cdi);
       
   390         }
       
   391         return locks;
       
   392     }
       
   393 
       
   394     /** Validate if the input CompositeData has the expected
       
   395      * CompositeType (i.e. contain all attributes with expected
       
   396      * names and types).
       
   397      */
       
   398     public static void validateCompositeData(CompositeData cd) {
       
   399         if (cd == null) {
       
   400             throw new NullPointerException("Null CompositeData");
       
   401         }
       
   402 
       
   403         CompositeType type = cd.getCompositeType();
       
   404         boolean currentVersion = true;
       
   405         if (!isTypeMatched(threadInfoCompositeType, type)) {
       
   406             currentVersion = false;
       
   407             // check if cd is an older version
       
   408             if (!isTypeMatched(threadInfoV5CompositeType, type) &&
       
   409                 !isTypeMatched(threadInfoV6CompositeType, type)) {
       
   410                 throw new IllegalArgumentException(
       
   411                     "Unexpected composite type for ThreadInfo");
       
   412             }
       
   413         }
       
   414 
       
   415         CompositeData[] stackTraceData =
       
   416             (CompositeData[]) cd.get(STACK_TRACE);
       
   417         if (stackTraceData == null) {
       
   418             throw new IllegalArgumentException(
       
   419                 "StackTraceElement[] is missing");
       
   420         }
       
   421         if (stackTraceData.length > 0) {
       
   422             StackTraceElementCompositeData.validateCompositeData(stackTraceData[0]);
       
   423         }
       
   424 
       
   425         // validate v6 attributes
       
   426         if (currentVersion) {
       
   427             CompositeData li = (CompositeData) cd.get(LOCK_INFO);
       
   428             if (li != null) {
       
   429                 if (!isTypeMatched(lockInfoCompositeType,
       
   430                                    li.getCompositeType())) {
       
   431                     throw new IllegalArgumentException(
       
   432                         "Unexpected composite type for \"" +
       
   433                         LOCK_INFO + "\" attribute.");
       
   434                 }
       
   435             }
       
   436 
       
   437             CompositeData[] lms = (CompositeData[]) cd.get(LOCKED_MONITORS);
       
   438             if (lms == null) {
       
   439                 throw new IllegalArgumentException("MonitorInfo[] is null");
       
   440             }
       
   441             if (lms.length > 0) {
       
   442                 MonitorInfoCompositeData.validateCompositeData(lms[0]);
       
   443             }
       
   444 
       
   445             CompositeData[] lsyncs = (CompositeData[]) cd.get(LOCKED_SYNCS);
       
   446             if (lsyncs == null) {
       
   447                 throw new IllegalArgumentException("LockInfo[] is null");
       
   448             }
       
   449             if (lsyncs.length > 0) {
       
   450                 if (!isTypeMatched(lockInfoCompositeType,
       
   451                                    lsyncs[0].getCompositeType())) {
       
   452                     throw new IllegalArgumentException(
       
   453                         "Unexpected composite type for \"" +
       
   454                         LOCKED_SYNCS + "\" attribute.");
       
   455                 }
       
   456             }
       
   457 
       
   458         }
       
   459     }
       
   460 
       
   461     private static final long serialVersionUID = 2464378539119753175L;
       
   462 }