001: /*
002: * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.management;
027:
028: import java.lang.management.ThreadInfo;
029: import java.lang.management.MonitorInfo;
030: import java.lang.management.LockInfo;
031: import javax.management.openmbean.CompositeType;
032: import javax.management.openmbean.CompositeData;
033: import javax.management.openmbean.CompositeDataSupport;
034: import javax.management.openmbean.OpenDataException;
035: import javax.management.openmbean.OpenType;
036:
037: /**
038: * A CompositeData for ThreadInfo for the local management support.
039: * This class avoids the performance penalty paid to the
040: * construction of a CompositeData use in the local case.
041: */
042: public class ThreadInfoCompositeData extends LazyCompositeData {
043: private final ThreadInfo threadInfo;
044: private final CompositeData cdata;
045: private final boolean currentVersion;
046:
047: private ThreadInfoCompositeData(ThreadInfo ti) {
048: this .threadInfo = ti;
049: this .currentVersion = true;
050: this .cdata = null;
051: }
052:
053: private ThreadInfoCompositeData(CompositeData cd) {
054: this .threadInfo = null;
055: this .currentVersion = ThreadInfoCompositeData
056: .isCurrentVersion(cd);
057: this .cdata = cd;
058: }
059:
060: public ThreadInfo getThreadInfo() {
061: return threadInfo;
062: }
063:
064: public boolean isCurrentVersion() {
065: return currentVersion;
066: }
067:
068: public static ThreadInfoCompositeData getInstance(CompositeData cd) {
069: validateCompositeData(cd);
070: return new ThreadInfoCompositeData(cd);
071: }
072:
073: public static CompositeData toCompositeData(ThreadInfo ti) {
074: ThreadInfoCompositeData ticd = new ThreadInfoCompositeData(ti);
075: return ticd.getCompositeData();
076: }
077:
078: protected CompositeData getCompositeData() {
079: // Convert StackTraceElement[] to CompositeData[]
080: StackTraceElement[] stackTrace = threadInfo.getStackTrace();
081: CompositeData[] stackTraceData = new CompositeData[stackTrace.length];
082: for (int i = 0; i < stackTrace.length; i++) {
083: StackTraceElement ste = stackTrace[i];
084: stackTraceData[i] = StackTraceElementCompositeData
085: .toCompositeData(ste);
086: }
087:
088: // Convert MonitorInfo[] and LockInfo[] to CompositeData[]
089: LockDataConverter converter = new LockDataConverter(threadInfo);
090: CompositeData lockInfoData = converter
091: .toLockInfoCompositeData();
092: CompositeData[] lockedSyncsData = converter
093: .toLockedSynchronizersCompositeData();
094:
095: // Convert MonitorInfo[] to CompositeData[]
096: MonitorInfo[] lockedMonitors = threadInfo.getLockedMonitors();
097: CompositeData[] lockedMonitorsData = new CompositeData[lockedMonitors.length];
098: for (int i = 0; i < lockedMonitors.length; i++) {
099: MonitorInfo mi = lockedMonitors[i];
100: lockedMonitorsData[i] = MonitorInfoCompositeData
101: .toCompositeData(mi);
102: }
103:
104: // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
105: // threadInfoItemNames!
106: final Object[] threadInfoItemValues = {
107: new Long(threadInfo.getThreadId()),
108: threadInfo.getThreadName(),
109: threadInfo.getThreadState().name(),
110: new Long(threadInfo.getBlockedTime()),
111: new Long(threadInfo.getBlockedCount()),
112: new Long(threadInfo.getWaitedTime()),
113: new Long(threadInfo.getWaitedCount()), lockInfoData,
114: threadInfo.getLockName(),
115: new Long(threadInfo.getLockOwnerId()),
116: threadInfo.getLockOwnerName(), stackTraceData,
117: new Boolean(threadInfo.isSuspended()),
118: new Boolean(threadInfo.isInNative()),
119: lockedMonitorsData, lockedSyncsData, };
120:
121: try {
122: return new CompositeDataSupport(threadInfoCompositeType,
123: threadInfoItemNames, threadInfoItemValues);
124: } catch (OpenDataException e) {
125: // Should never reach here
126: throw Util.newInternalError(e);
127: }
128: }
129:
130: // Attribute names
131: private static final String THREAD_ID = "threadId";
132: private static final String THREAD_NAME = "threadName";
133: private static final String THREAD_STATE = "threadState";
134: private static final String BLOCKED_TIME = "blockedTime";
135: private static final String BLOCKED_COUNT = "blockedCount";
136: private static final String WAITED_TIME = "waitedTime";
137: private static final String WAITED_COUNT = "waitedCount";
138: private static final String LOCK_INFO = "lockInfo";
139: private static final String LOCK_NAME = "lockName";
140: private static final String LOCK_OWNER_ID = "lockOwnerId";
141: private static final String LOCK_OWNER_NAME = "lockOwnerName";
142: private static final String STACK_TRACE = "stackTrace";
143: private static final String SUSPENDED = "suspended";
144: private static final String IN_NATIVE = "inNative";
145: private static final String LOCKED_MONITORS = "lockedMonitors";
146: private static final String LOCKED_SYNCS = "lockedSynchronizers";
147:
148: private static final String[] threadInfoItemNames = { THREAD_ID,
149: THREAD_NAME, THREAD_STATE, BLOCKED_TIME, BLOCKED_COUNT,
150: WAITED_TIME, WAITED_COUNT, LOCK_INFO, LOCK_NAME,
151: LOCK_OWNER_ID, LOCK_OWNER_NAME, STACK_TRACE, SUSPENDED,
152: IN_NATIVE, LOCKED_MONITORS, LOCKED_SYNCS, };
153:
154: // New attributes added in 6.0 ThreadInfo
155: private static final String[] threadInfoV6Attributes = { LOCK_INFO,
156: LOCKED_MONITORS, LOCKED_SYNCS, };
157:
158: // Current version of ThreadInfo
159: private static final CompositeType threadInfoCompositeType;
160: // Previous version of ThreadInfo
161: private static final CompositeType threadInfoV5CompositeType;
162: private static final CompositeType lockInfoCompositeType;
163: static {
164: try {
165: threadInfoCompositeType = (CompositeType) MappedMXBeanType
166: .toOpenType(ThreadInfo.class);
167: // Form a CompositeType for JDK 5.0 ThreadInfo version
168: String[] itemNames = threadInfoCompositeType.keySet()
169: .toArray(new String[0]);
170: int numV5Attributes = threadInfoItemNames.length
171: - threadInfoV6Attributes.length;
172: String[] v5ItemNames = new String[numV5Attributes];
173: String[] v5ItemDescs = new String[numV5Attributes];
174: OpenType[] v5ItemTypes = new OpenType[numV5Attributes];
175: int i = 0;
176: for (String n : itemNames) {
177: if (isV5Attribute(n)) {
178: v5ItemNames[i] = n;
179: v5ItemDescs[i] = threadInfoCompositeType
180: .getDescription(n);
181: v5ItemTypes[i] = threadInfoCompositeType.getType(n);
182: i++;
183: }
184: }
185:
186: threadInfoV5CompositeType = new CompositeType(
187: "java.lang.management.ThreadInfo",
188: "J2SE 5.0 java.lang.management.ThreadInfo",
189: v5ItemNames, v5ItemDescs, v5ItemTypes);
190: } catch (OpenDataException e) {
191: // Should never reach here
192: throw Util.newInternalError(e);
193: }
194:
195: // Each CompositeData object has its CompositeType associated
196: // with it. So we can get the CompositeType representing LockInfo
197: // from a mapped CompositeData for any LockInfo object.
198: // Thus we construct a random LockInfo object and pass it
199: // to LockDataConverter to do the conversion.
200: Object o = new Object();
201: LockInfo li = new LockInfo(o.getClass().getName(), System
202: .identityHashCode(o));
203: CompositeData cd = LockDataConverter
204: .toLockInfoCompositeData(li);
205: lockInfoCompositeType = cd.getCompositeType();
206: }
207:
208: private static boolean isV5Attribute(String itemName) {
209: for (String n : threadInfoV6Attributes) {
210: if (itemName.equals(n)) {
211: return false;
212: }
213: }
214: return true;
215: }
216:
217: public static boolean isCurrentVersion(CompositeData cd) {
218: if (cd == null) {
219: throw new NullPointerException("Null CompositeData");
220: }
221:
222: return isTypeMatched(threadInfoCompositeType, cd
223: .getCompositeType());
224: }
225:
226: public long threadId() {
227: return getLong(cdata, THREAD_ID);
228: }
229:
230: public String threadName() {
231: // The ThreadName item cannot be null so we check that
232: // it is present with a non-null value.
233: String name = getString(cdata, THREAD_NAME);
234: if (name == null) {
235: throw new IllegalArgumentException(
236: "Invalid composite data: " + "Attribute "
237: + THREAD_NAME + " has null value");
238: }
239: return name;
240: }
241:
242: public Thread.State threadState() {
243: return Thread.State.valueOf(getString(cdata, THREAD_STATE));
244: }
245:
246: public long blockedTime() {
247: return getLong(cdata, BLOCKED_TIME);
248: }
249:
250: public long blockedCount() {
251: return getLong(cdata, BLOCKED_COUNT);
252: }
253:
254: public long waitedTime() {
255: return getLong(cdata, WAITED_TIME);
256: }
257:
258: public long waitedCount() {
259: return getLong(cdata, WAITED_COUNT);
260: }
261:
262: public String lockName() {
263: // The LockName and LockOwnerName can legitimately be null,
264: // we don't bother to check the value
265: return getString(cdata, LOCK_NAME);
266: }
267:
268: public long lockOwnerId() {
269: return getLong(cdata, LOCK_OWNER_ID);
270: }
271:
272: public String lockOwnerName() {
273: return getString(cdata, LOCK_OWNER_NAME);
274: }
275:
276: public boolean suspended() {
277: return getBoolean(cdata, SUSPENDED);
278: }
279:
280: public boolean inNative() {
281: return getBoolean(cdata, IN_NATIVE);
282: }
283:
284: public StackTraceElement[] stackTrace() {
285: CompositeData[] stackTraceData = (CompositeData[]) cdata
286: .get(STACK_TRACE);
287:
288: // The StackTrace item cannot be null, but if it is we will get
289: // a NullPointerException when we ask for its length.
290: StackTraceElement[] stackTrace = new StackTraceElement[stackTraceData.length];
291: for (int i = 0; i < stackTraceData.length; i++) {
292: CompositeData cdi = stackTraceData[i];
293: stackTrace[i] = StackTraceElementCompositeData.from(cdi);
294: }
295: return stackTrace;
296: }
297:
298: // 6.0 new attributes
299: public LockInfo lockInfo() {
300: LockDataConverter converter = new LockDataConverter();
301: CompositeData lockInfoData = (CompositeData) cdata
302: .get(LOCK_INFO);
303: return converter.toLockInfo(lockInfoData);
304: }
305:
306: public MonitorInfo[] lockedMonitors() {
307: CompositeData[] lockedMonitorsData = (CompositeData[]) cdata
308: .get(LOCKED_MONITORS);
309:
310: // The LockedMonitors item cannot be null, but if it is we will get
311: // a NullPointerException when we ask for its length.
312: MonitorInfo[] monitors = new MonitorInfo[lockedMonitorsData.length];
313: for (int i = 0; i < lockedMonitorsData.length; i++) {
314: CompositeData cdi = lockedMonitorsData[i];
315: monitors[i] = MonitorInfo.from(cdi);
316: }
317: return monitors;
318: }
319:
320: public LockInfo[] lockedSynchronizers() {
321: LockDataConverter converter = new LockDataConverter();
322: CompositeData[] lockedSyncsData = (CompositeData[]) cdata
323: .get(LOCKED_SYNCS);
324:
325: // The LockedSynchronizers item cannot be null, but if it is we will
326: // get a NullPointerException when we ask for its length.
327: return converter.toLockedSynchronizers(lockedSyncsData);
328: }
329:
330: /** Validate if the input CompositeData has the expected
331: * CompositeType (i.e. contain all attributes with expected
332: * names and types).
333: */
334: public static void validateCompositeData(CompositeData cd) {
335: if (cd == null) {
336: throw new NullPointerException("Null CompositeData");
337: }
338:
339: CompositeType type = cd.getCompositeType();
340: boolean currentVersion = true;
341: if (!isTypeMatched(threadInfoCompositeType, type)) {
342: currentVersion = false;
343: // check if cd is an older version
344: if (!isTypeMatched(threadInfoV5CompositeType, type)) {
345: throw new IllegalArgumentException(
346: "Unexpected composite type for ThreadInfo");
347: }
348: }
349:
350: CompositeData[] stackTraceData = (CompositeData[]) cd
351: .get(STACK_TRACE);
352: if (stackTraceData == null) {
353: throw new IllegalArgumentException(
354: "StackTraceElement[] is missing");
355: }
356: if (stackTraceData.length > 0) {
357: StackTraceElementCompositeData
358: .validateCompositeData(stackTraceData[0]);
359: }
360:
361: // validate v6 attributes
362: if (currentVersion) {
363: CompositeData li = (CompositeData) cd.get(LOCK_INFO);
364: if (li != null) {
365: if (!isTypeMatched(lockInfoCompositeType, li
366: .getCompositeType())) {
367: throw new IllegalArgumentException(
368: "Unexpected composite type for \""
369: + LOCK_INFO + "\" attribute.");
370: }
371: }
372:
373: CompositeData[] lms = (CompositeData[]) cd
374: .get(LOCKED_MONITORS);
375: if (lms == null) {
376: throw new IllegalArgumentException(
377: "MonitorInfo[] is null");
378: }
379: if (lms.length > 0) {
380: MonitorInfoCompositeData.validateCompositeData(lms[0]);
381: }
382:
383: CompositeData[] lsyncs = (CompositeData[]) cd
384: .get(LOCKED_SYNCS);
385: if (lsyncs == null) {
386: throw new IllegalArgumentException("LockInfo[] is null");
387: }
388: if (lsyncs.length > 0) {
389: if (!isTypeMatched(lockInfoCompositeType, lsyncs[0]
390: .getCompositeType())) {
391: throw new IllegalArgumentException(
392: "Unexpected composite type for \""
393: + LOCKED_SYNCS + "\" attribute.");
394: }
395: }
396:
397: }
398: }
399: }
|