Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/jcl/src/java.management/share/classes/java/lang/management/ThreadInfo.java
12511 views
1
/*[INCLUDE-IF JAVA_SPEC_VERSION >= 8]*/
2
/*
3
*******************************************************************************
4
* Copyright (c) 2007, 2022 IBM Corp. and others
5
*
6
* This program and the accompanying materials are made available under
7
* the terms of the Eclipse Public License 2.0 which accompanies this
8
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
9
* or the Apache License, Version 2.0 which accompanies this distribution and
10
* is available at https://www.apache.org/licenses/LICENSE-2.0.
11
*
12
* This Source Code may also be made available under the following
13
* Secondary Licenses when the conditions for such availability set
14
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
15
* General Public License, version 2 with the GNU Classpath
16
* Exception [1] and GNU General Public License, version 2 with the
17
* OpenJDK Assembly Exception [2].
18
*
19
* [1] https://www.gnu.org/software/classpath/license.html
20
* [2] http://openjdk.java.net/legal/assembly-exception.html
21
*
22
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
23
*******************************************************************************/
24
package java.lang.management;
25
26
import java.util.Arrays;
27
import java.util.StringTokenizer;
28
29
import javax.management.openmbean.CompositeData;
30
import javax.management.openmbean.InvalidKeyException;
31
32
import com.ibm.java.lang.management.internal.LockInfoUtil;
33
import com.ibm.java.lang.management.internal.ManagementAccessControl;
34
import com.ibm.java.lang.management.internal.MonitorInfoUtil;
35
import com.ibm.java.lang.management.internal.StackTraceElementUtil;
36
import com.ibm.java.lang.management.internal.ThreadInfoUtil;
37
38
import openj9.management.internal.LockInfoBase;
39
import openj9.management.internal.MonitorInfoBase;
40
import openj9.management.internal.ThreadInfoBase;
41
42
/**
43
* Information about a snapshot of the state of a thread.
44
*
45
* @since 1.5
46
*/
47
public class ThreadInfo {
48
49
private static final MonitorInfo[] EMPTY_MONITORINFO_ARRAY = new MonitorInfo[0];
50
51
/* Set up access to ThreadInfo shared secret.*/
52
static {
53
ManagementAccessControl.setThreadInfoAccess(new ThreadInfoAccessImpl());
54
}
55
56
/**
57
* Container for the actual data.
58
*/
59
private final ThreadInfoBase baseInfo;
60
private static final LockInfo[] EMPTY_LOCKINFO_ARRAY = new LockInfo[0];
61
62
63
/**
64
* Used by from().
65
* @param threadIdVal
66
* @param threadNameVal
67
* @param threadStateVal
68
* @param suspendedVal
69
* @param inNativeVal
70
* @param blockedCountVal
71
* @param blockedTimeVal
72
* @param waitedCountVal
73
* @param waitedTimeVal
74
* @param lockNameVal
75
* @param lockOwnerIdVal
76
* @param lockOwnerNameVal
77
* @param stackTraceVal
78
* @param lockInfo
79
* @param lockedMonitors
80
* @param lockedSynchronizers
81
/*[IF Sidecar19-SE]
82
* @param daemon
83
* @param priority
84
/*[ENDIF]
85
*/
86
private ThreadInfo(long threadIdVal, String threadNameVal,
87
Thread.State threadStateVal, boolean suspendedVal,
88
boolean inNativeVal, long blockedCountVal, long blockedTimeVal,
89
long waitedCountVal, long waitedTimeVal, String lockNameVal,
90
long lockOwnerIdVal, String lockOwnerNameVal,
91
StackTraceElement[] stackTraceVal, LockInfo lockInfo,
92
MonitorInfo[] lockedMonitors, LockInfo[] lockedSynchronizers
93
/*[IF Sidecar19-SE]*/
94
, boolean daemon, int priority
95
/*[ENDIF]*/
96
) {
97
MonitorInfoBase[] monInfoBases = null;
98
if (null != lockedMonitors) {
99
monInfoBases = Arrays.stream(lockedMonitors)
100
.map(MonitorInfo::getBaseInfo).toArray(MonitorInfoBase[]::new);
101
}
102
103
LockInfoBase[] lockedSyncs = null;
104
if (null != lockedSynchronizers) {
105
lockedSyncs = Arrays.stream(lockedSynchronizers)
106
.map(LockInfo::getBaseInfo).toArray(LockInfoBase[]::new);
107
}
108
LockInfoBase lckInfo = null;
109
if (null != lockInfo) {
110
lckInfo = lockInfo.getBaseInfo();
111
}
112
baseInfo = new ThreadInfoBase(threadIdVal, threadNameVal, threadStateVal, suspendedVal, inNativeVal,
113
blockedCountVal, blockedTimeVal, waitedCountVal, waitedTimeVal, lockNameVal, lockOwnerIdVal,
114
lockOwnerNameVal, stackTraceVal, lckInfo, monInfoBases, lockedSyncs
115
/*[IF Sidecar19-SE]*/
116
, daemon, priority
117
/*[ENDIF]*/
118
);
119
}
120
121
/**
122
* Constructor for use via reflection from ThreadMXBeanImpl.
123
* @param base data for the object
124
*/
125
private ThreadInfo(ThreadInfoBase base) {
126
baseInfo = base;
127
}
128
129
/**
130
* Returns the number of times that the thread represented by this
131
* <code>ThreadInfo</code> has been blocked on any monitor objects. The
132
* count is from the start of the thread's life.
133
*
134
* @return the number of times the corresponding thread has been blocked on
135
* a monitor.
136
*/
137
public long getBlockedCount() {
138
return baseInfo.getBlockedCount();
139
}
140
141
/**
142
* If thread contention monitoring is supported and enabled, returns the
143
* total amount of time that the thread represented by this
144
* <code>ThreadInfo</code> has spent blocked on any monitor objects. The
145
* time is measured in milliseconds and will be measured over the time period
146
* since thread contention was most recently enabled.
147
*
148
* @return if thread contention monitoring is currently enabled, the number
149
* of milliseconds that the thread associated with this
150
* <code>ThreadInfo</code> has spent blocked on any monitors. If
151
* thread contention monitoring is supported but currently disabled,
152
* <code>-1</code>.
153
* @throws UnsupportedOperationException
154
* if the virtual machine does not support thread contention
155
* monitoring.
156
* @see ThreadMXBean#isThreadContentionMonitoringSupported()
157
* @see ThreadMXBean#isThreadContentionMonitoringEnabled()
158
*/
159
public long getBlockedTime() {
160
return baseInfo.getBlockedTime();
161
}
162
163
/**
164
* If the thread represented by this <code>ThreadInfo</code> is currently
165
* blocked on or waiting on a monitor object, returns a string
166
* representation of that monitor object.
167
* <p>
168
* The monitor's string representation is comprised of the following
169
* component parts:
170
* <ul>
171
* <li><code>monitor</code> class name
172
* <li><code>@</code>
173
* <li><code>Integer.toHexString(System.identityHashCode(monitor))</code>
174
* </ul>
175
* @return if blocked or waiting on a monitor, a string representation of
176
* the monitor object. Otherwise, <code>null</code>.
177
* @see Integer#toHexString(int)
178
* @see System#identityHashCode(java.lang.Object)
179
*/
180
public String getLockName() {
181
return baseInfo.getLockName();
182
}
183
184
/**
185
* If the thread represented by this <code>ThreadInfo</code> is currently
186
* blocked on or waiting on a monitor object, returns the thread identifier
187
* of the thread which owns the monitor.
188
*
189
* @return the thread identifier of the other thread which holds the monitor
190
* that the thread associated with this <code>ThreadInfo</code> is
191
* blocked or waiting on. If this <code>ThreadInfo</code>'s
192
* associated thread is currently not blocked or waiting, or there
193
* is no other thread holding the monitor, returns a <code>-1</code>.
194
*/
195
public long getLockOwnerId() {
196
return baseInfo.getLockOwnerId();
197
}
198
199
/**
200
* If the thread represented by this <code>ThreadInfo</code> is currently
201
* blocked on or waiting on a monitor object, returns the name of the thread
202
* which owns the monitor.
203
*
204
* @return the name of the other thread which holds the monitor that the
205
* thread associated with this <code>ThreadInfo</code> is blocked
206
* or waiting on. If this <code>ThreadInfo</code>'s associated
207
* thread is currently not blocked or waiting, or there is no other
208
* thread holding the monitor, returns a <code>null</code>
209
* reference.
210
*/
211
public String getLockOwnerName() {
212
return baseInfo.getLockOwnerName();
213
}
214
215
/**
216
* If the thread corresponding to this <code>ThreadInfo</code> is blocked
217
* then this method returns a {@link LockInfo} object that contains details
218
* of the associated lock object.
219
*
220
* @return a <code>LockInfo</code> object if this <code>ThreadInfo</code>'s
221
* thread is currently blocked, else <code>null</code>.
222
*/
223
public LockInfo getLockInfo() {
224
LockInfoBase li = baseInfo.getBlockingLockInfo();
225
return (null == li) ? null : new LockInfo(li);
226
}
227
228
/**
229
* Returns the native thread identifier of the thread represented by this
230
* <code>ThreadInfo</code>.
231
*
232
* @return the native identifier of the thread corresponding to this
233
* <code>ThreadInfo</code>.
234
*/
235
long getNativeThreadId() {
236
return baseInfo.getNativeTId();
237
}
238
239
/**
240
* If available, returns the stack trace for the thread represented by this
241
* <code>ThreadInfo</code> instance. The stack trace is returned in an
242
* array of {@link StackTraceElement} objects with the &quot;top&quot; of the
243
* stack encapsulated in the first array element and the &quot;bottom&quot;
244
* of the stack in the last array element.
245
* <p>
246
* If this <code>ThreadInfo</code> was created without any stack trace
247
* information (e.g. by a call to {@link ThreadMXBean#getThreadInfo(long)})
248
* then the returned array will have a length of zero.
249
* </p>
250
*
251
* @return the stack trace for the thread represented by this
252
* <code>ThreadInfo</code>.
253
*/
254
public StackTraceElement[] getStackTrace() {
255
return baseInfo.getStackTrace().clone();
256
}
257
258
/**
259
* Returns the thread identifier of the thread represented by this
260
* <code>ThreadInfo</code>.
261
*
262
* @return the identifier of the thread corresponding to this
263
* <code>ThreadInfo</code>.
264
*/
265
public long getThreadId() {
266
return baseInfo.getThreadId();
267
}
268
269
/**
270
* Returns the name of the thread represented by this
271
* <code>ThreadInfo</code>.
272
*
273
* @return the name of the thread corresponding to this
274
* <code>ThreadInfo</code>.
275
*/
276
public String getThreadName() {
277
return baseInfo.getThreadName();
278
}
279
280
/**
281
* Returns the thread state value of the thread represented by this
282
* <code>ThreadInfo</code>.
283
*
284
* @return the thread state of the thread corresponding to this
285
* <code>ThreadInfo</code>.
286
* @see Thread#getState()
287
*/
288
public Thread.State getThreadState() {
289
return baseInfo.getThreadState();
290
}
291
292
/**
293
* The number of times that the thread represented by this
294
* <code>ThreadInfo</code> has gone to the &quot;wait&quot; or &quot;timed
295
* wait&quot; state.
296
*
297
* @return the number of times the corresponding thread has been in the
298
* &quot;wait&quot; or &quot;timed wait&quot; state.
299
*/
300
public long getWaitedCount() {
301
return baseInfo.getWaitedCount();
302
}
303
304
/**
305
* If thread contention monitoring is supported and enabled, returns the
306
* total amount of time that the thread represented by this
307
* <code>ThreadInfo</code> has spent waiting for notifications. The time
308
* is measured in milliseconds and will be measured over the time period
309
* since thread contention was most recently enabled.
310
*
311
* @return if thread contention monitoring is currently enabled, the number
312
* of milliseconds that the thread associated with this
313
* <code>ThreadInfo</code> has spent waiting notifications. If
314
* thread contention monitoring is supported but currently disabled,
315
* <code>-1</code>.
316
* @throws UnsupportedOperationException
317
* if the virtual machine does not support thread contention
318
* monitoring.
319
* @see ThreadMXBean#isThreadContentionMonitoringSupported()
320
* @see ThreadMXBean#isThreadContentionMonitoringEnabled()
321
*/
322
public long getWaitedTime() {
323
return baseInfo.getWaitedTime();
324
}
325
326
/**
327
* Returns a <code>boolean</code> indication of whether or not the thread
328
* represented by this <code>ThreadInfo</code> is currently in a native
329
* method.
330
*
331
* @return if the corresponding thread <i>is </i> executing a native method
332
* then <code>true</code>, otherwise <code>false</code>.
333
*/
334
public boolean isInNative() {
335
return baseInfo.isInNative();
336
}
337
338
/**
339
* Returns a <code>boolean</code> indication of whether or not the thread
340
* represented by this <code>ThreadInfo</code> is currently suspended.
341
*
342
* @return if the corresponding thread <i>is </i> suspended then
343
* <code>true</code>, otherwise <code>false</code>.
344
*/
345
public boolean isSuspended() {
346
return baseInfo.isSuspended();
347
}
348
349
/**
350
* Returns an array of <code>MonitorInfo</code> objects, one for every
351
* monitor object locked by the <code>Thread</code> corresponding to this
352
* <code>ThreadInfo</code> when it was instantiated.
353
*
354
* @return an array whose elements comprise of <code>MonitorInfo</code>
355
* objects - one for each object monitor locked by this
356
* <code>ThreadInfo</code> object's corresponding thread. If no
357
* monitors are locked by the thread then the array will have a
358
* length of zero.
359
*/
360
public MonitorInfo[] getLockedMonitors() {
361
MonitorInfo lockedMons[] = null;
362
MonitorInfoBase[] lockedMonBases = baseInfo.getLockedMonitors();
363
if (null != lockedMonBases) {
364
lockedMons = Arrays.stream(lockedMonBases)
365
.map(MonitorInfo::new).toArray(MonitorInfo[]::new);
366
}
367
return lockedMons;
368
}
369
370
/**
371
* Returns an array of <code>LockInfo</code> objects, each one containing
372
* information on an ownable synchronizer (a synchronizer that makes use of
373
* the <code>AbstractOwnableSynchronizer</code> type and which is
374
* completely owned by a single thread) locked by the <code>Thread</code>
375
* corresponding to this <code>ThreadInfo</code> when it was instantiated.
376
*
377
* @return an array whose elements comprise of <code>LockInfo</code>
378
* objects - one for each ownable synchronizer locked by this
379
* <code>ThreadInfo</code> object's corresponding thread. If no
380
* ownable synchronizer are locked by the thread then the array will
381
* have a length of zero.
382
*/
383
public LockInfo[] getLockedSynchronizers() {
384
LockInfo lockedSyncs[] = null;
385
LockInfoBase[] lockedSyncBases = baseInfo.getLockedSynchronizers();
386
lockedSyncs = Arrays.stream(lockedSyncBases)
387
.map(LockInfo::new).toArray(LockInfo[]::new);
388
return lockedSyncs;
389
}
390
391
/**
392
* Receives a {@link CompositeData} representing a <code>ThreadInfo</code>
393
* object and attempts to return the root <code>ThreadInfo</code>
394
* instance.
395
*
396
* @param cd
397
* a <code>CompositeData</code> that represents a
398
* <code>ThreadInfo</code>.
399
* @return if <code>cd</code> is non- <code>null</code>, returns a new
400
* instance of <code>ThreadInfo</code>. If <code>cd</code> is
401
* <code>null</code>, returns <code>null</code>.
402
* @throws IllegalArgumentException
403
* if argument <code>cd</code> does not correspond to a
404
* <code>ThreadInfo</code> with the following attributes:
405
* <ul>
406
* <li><code>threadId</code>(<code>java.lang.Long</code>)
407
* <li><code>threadName</code>(
408
* <code>java.lang.String</code>)
409
* <li><code>threadState</code>(
410
* <code>java.lang.String</code>)
411
* <li><code>suspended</code>(
412
* <code>java.lang.Boolean</code>)
413
* <li><code>inNative</code>(<code>java.lang.Boolean</code>)
414
* <li><code>blockedCount</code>(
415
* <code>java.lang.Long</code>)
416
* <li><code>blockedTime</code>(<code>java.lang.Long</code>)
417
* <li><code>waitedCount</code>(<code>java.lang.Long</code>)
418
* <li><code>waitedTime</code> (<code>java.lang.Long</code>)
419
/*[IF Sidecar19-SE]
420
* <li><code>daemon</code> (<code>java.lang.Boolean</code>)
421
* <li><code>priority</code> (<code>java.lang.Integer</code>)
422
/*[ENDIF]
423
* <li><code>lockInfo</code> (<code>javax.management.openmbean.CompositeData</code>)
424
* which holds the simple attributes <code>className</code>(<code>java.lang.String</code>),
425
* <code>identityHashCode</code>(<code>java.lang.Integer</code>).
426
* In the event that the input <code>CompositeData</code> does not hold a
427
* <code>lockInfo</code> attribute, the value of the <code>lockName</code>
428
* attribute is used for setting the returned object's
429
* <code>LockInfo</code> state.
430
* <li><code>lockName</code> (<code>java.lang.String</code>)
431
* <li><code>lockOwnerId</code> (<code>java.lang.Long</code>)
432
* <li><code>lockOwnerName</code> (<code>java.lang.String</code>)
433
* <li><code>stackTrace</code> (<code>javax.management.openmbean.CompositeData[]</code>)
434
* </ul>
435
* Each element of the <code>stackTrace</code> array must
436
* correspond to a <code>java.lang.StackTraceElement</code>
437
* and have the following attributes :
438
* <ul>
439
/*[IF Sidecar19-SE]
440
* <li><code>moduleName</code>(<code>java.lang.String</code>)
441
* <li><code>moduleVersion</code>(<code>java.lang.String</code>)
442
/*[ENDIF]
443
* <li><code>className</code> (<code>java.lang.String</code>)
444
* <li><code>methodName</code> (<code>java.lang.String</code>)
445
* <li><code>fileName</code> (<code>java.lang.String</code>)
446
* <li><code>lineNumber</code> (<code>java.lang.Integer</code>)
447
* <li><code>nativeMethod</code> (<code>java.lang.Boolean</code>)
448
* </ul>
449
*/
450
public static ThreadInfo from(CompositeData cd) {
451
ThreadInfo result = null;
452
453
if (cd != null) {
454
// Is the received CompositeData of the required type to create
455
// a new ThreadInfo ?
456
if (!ThreadInfoUtil.getCompositeType().isValue(cd)) {
457
/*[MSG "K05E5", "CompositeData is not of the expected type."]*/
458
throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K05E5")); //$NON-NLS-1$
459
}
460
461
long threadIdVal;
462
String threadNameVal;
463
String threadStateStringVal;
464
Thread.State threadStateVal;
465
boolean suspendedVal;
466
boolean inNativeVal;
467
long blockedCountVal;
468
long blockedTimeVal;
469
long waitedCountVal;
470
long waitedTimeVal;
471
String lockNameVal;
472
long lockOwnerIdVal;
473
String lockOwnerNameVal;
474
StackTraceElement[] stackTraceVals;
475
LockInfo lockInfoVal;
476
MonitorInfo[] lockedMonitorVals;
477
LockInfo[] lockedSynchronizerVals;
478
479
/*[IF Sidecar19-SE]*/
480
boolean daemonVal;
481
int priorityVal;
482
/*[ENDIF]*/
483
484
try {
485
// Set the mandatory attributes - if any of these are
486
// missing we need to throw a IllegalArgumentException
487
threadIdVal = ((Long) cd.get("threadId")).longValue(); //$NON-NLS-1$
488
threadNameVal = (String) cd.get("threadName"); //$NON-NLS-1$
489
threadStateStringVal = (String) cd.get("threadState"); //$NON-NLS-1$
490
491
// Verify that threadStateStringVal contains a string that can
492
// be successfully used to create a Thread.State.
493
try {
494
threadStateVal = Thread.State.valueOf(threadStateStringVal);
495
} catch (IllegalArgumentException e) {
496
/*[MSG "K0612", "CompositeData contains an unexpected threadState value."]*/
497
throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K0612", e)); //$NON-NLS-1$
498
}
499
500
suspendedVal = ((Boolean) cd.get("suspended")).booleanValue(); //$NON-NLS-1$
501
inNativeVal = ((Boolean) cd.get("inNative")).booleanValue(); //$NON-NLS-1$
502
blockedCountVal = ((Long) cd.get("blockedCount")).longValue(); //$NON-NLS-1$
503
blockedTimeVal = ((Long) cd.get("blockedTime")).longValue(); //$NON-NLS-1$
504
waitedCountVal = ((Long) cd.get("waitedCount")).longValue(); //$NON-NLS-1$
505
waitedTimeVal = ((Long) cd.get("waitedTime")).longValue(); //$NON-NLS-1$
506
lockNameVal = (String) cd.get("lockName"); //$NON-NLS-1$
507
lockOwnerIdVal = ((Long) cd.get("lockOwnerId")).longValue(); //$NON-NLS-1$
508
lockOwnerNameVal = (String) cd.get("lockOwnerName"); //$NON-NLS-1$
509
CompositeData[] stackTraceDataVal = (CompositeData[]) cd.get("stackTrace"); //$NON-NLS-1$
510
stackTraceVals = StackTraceElementUtil.fromArray(stackTraceDataVal);
511
512
/*[IF Sidecar19-SE]*/
513
daemonVal = ((Boolean) cd.get("daemon")).booleanValue(); //$NON-NLS-1$
514
priorityVal = ((Integer) cd.get("priority")).intValue(); //$NON-NLS-1$
515
/*[ENDIF]*/
516
} catch (NullPointerException | InvalidKeyException e) {
517
// throw an IllegalArgumentException as the CompositeData
518
// object does not contain an expected key
519
/*[MSG "K05E6", "CompositeData object does not contain expected key."]*/
520
throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K05E6")); //$NON-NLS-1$
521
}
522
523
// Attempt to set the optional attributes - if any of these
524
// are missing we need to use the recommended default values.
525
lockInfoVal = recoverLockInfoAttribute(cd, lockNameVal);
526
lockedMonitorVals = recoverLockedMonitors(cd);
527
lockedSynchronizerVals = recoverLockedSynchronizers(cd);
528
529
// Finally, try and create the resulting ThreadInfo
530
result = new ThreadInfo(threadIdVal, threadNameVal, threadStateVal,
531
suspendedVal, inNativeVal, blockedCountVal, blockedTimeVal,
532
waitedCountVal, waitedTimeVal, lockNameVal, lockOwnerIdVal,
533
lockOwnerNameVal, stackTraceVals, lockInfoVal,
534
lockedMonitorVals, lockedSynchronizerVals
535
/*[IF Sidecar19-SE]*/
536
, daemonVal, priorityVal
537
/*[ENDIF]*/
538
);
539
}
540
541
return result;
542
}
543
544
/**
545
* Helper method to retrieve an array of <code>LockInfo</code> from the
546
* supplied <code>CompositeData</code> object.
547
*
548
* @param cd
549
* a <code>CompositeData</code> that is expected to map to a
550
* <code>ThreadInfo</code> object
551
* @return an array of <code>LockInfo</code>
552
*/
553
private static LockInfo[] recoverLockedSynchronizers(CompositeData cd) {
554
LockInfo[] result;
555
try {
556
CompositeData[] lockedSynchronizersDataVal = (CompositeData[]) cd.get("lockedSynchronizers"); //$NON-NLS-1$
557
result = LockInfoUtil.fromArray(lockedSynchronizersDataVal);
558
} catch (InvalidKeyException e) {
559
result = EMPTY_LOCKINFO_ARRAY;
560
}
561
return result;
562
}
563
564
/**
565
* Helper method to retrieve an array of <code>MonitorInfo</code> from the
566
* supplied <code>CompositeData</code> object.
567
*
568
* @param cd
569
* a <code>CompositeData</code> that is expected to map to a
570
* <code>ThreadInfo</code> object
571
* @return an array of <code>MonitorInfo</code>
572
*/
573
private static MonitorInfo[] recoverLockedMonitors(CompositeData cd) {
574
MonitorInfo[] result;
575
try {
576
CompositeData[] lockedMonitorsDataVal = (CompositeData[]) cd.get("lockedMonitors"); //$NON-NLS-1$
577
result = MonitorInfoUtil.fromArray(lockedMonitorsDataVal);
578
} catch (InvalidKeyException e) {
579
result = EMPTY_MONITORINFO_ARRAY;
580
}
581
return result;
582
}
583
584
/**
585
* Helper method that retrieves a <code>LockInfo</code> value from the
586
* supplied <code>CompositeData</code> that is expected to map to a
587
* <code>ThreadInfo</code> instance.
588
*
589
* @param cd
590
* a <code>CompositeData</code> that maps to a
591
* <code>ThreadInfo</code>
592
* @param lockNameVal
593
* the name of a lock in the format specified by the
594
* {@link #getLockName()} method. If the input <code>cd</code>
595
* does not contain a &quot;lockInfo&quot; value this parameter
596
* will be used to construct the return value
597
* @return a new <code>LockInfo</code> either constructed using data
598
* recovered from the <code>cd</code> input or, if that fails,
599
* from the <code>lockNameVal</code> parameter
600
*/
601
private static LockInfo recoverLockInfoAttribute(CompositeData cd, String lockNameVal) {
602
LockInfo result = null;
603
try {
604
CompositeData lockInfoCDVal = cd.get("lockInfo") != null //$NON-NLS-1$
605
? (CompositeData) cd.get("lockInfo") //$NON-NLS-1$
606
: null;
607
if (lockInfoCDVal != null) {
608
// Is the received CompositeData of the required type to create
609
// a new ThreadInfo ?
610
if (!LockInfoUtil.getCompositeType().isValue(lockInfoCDVal)) {
611
/*[MSG "K05E5", "CompositeData is not of the expected type."]*/
612
throw new IllegalArgumentException(com.ibm.oti.util.Msg.getString("K05E5")); //$NON-NLS-1$
613
}
614
result = new LockInfo(
615
((String) lockInfoCDVal.get("className")), //$NON-NLS-1$
616
((Integer) lockInfoCDVal.get("identityHashCode")).intValue()); //$NON-NLS-1$
617
}
618
} catch (InvalidKeyException e) {
619
// Create a default LockInfo using the information from
620
// the lockName attribute which should have been recovered
621
// above
622
result = createLockInfoFromLockName(lockNameVal);
623
}
624
return result;
625
}
626
627
/*[IF Sidecar19-SE]*/
628
629
/**
630
* Returns a <code>boolean</code> indication of whether or not the thread
631
* represented by this <code>ThreadInfo</code> is currently a daemon thread.
632
*
633
* @return <code>true</code> if this thread is a daemon thread, otherwise <code>false</code> .
634
*/
635
public boolean isDaemon() {
636
return baseInfo.isDaemon();
637
}
638
639
/**
640
* Returns the thread priority of the thread represented by this <code>ThreadInfo</code>.
641
*
642
* @return The priority of the thread represented by this <code>ThreadInfo</code>.
643
*/
644
public int getPriority() {
645
return baseInfo.getPriority();
646
}
647
648
/*[ENDIF]*/
649
650
/**
651
* @return a text description of this thread.
652
*/
653
@Override
654
public String toString() {
655
return baseInfo.toString();
656
}
657
658
/**
659
* {@inheritDoc}
660
*/
661
@Override
662
public boolean equals(Object obj) {
663
boolean result = (this == obj);
664
if (!result && (null != obj) && (obj instanceof ThreadInfo)) {
665
result = baseInfo.equals(((ThreadInfo) obj).baseInfo);
666
}
667
return result;
668
}
669
670
/**
671
* {@inheritDoc}
672
*/
673
@Override
674
public int hashCode() {
675
return baseInfo.hashCode();
676
}
677
678
/**
679
* Convenience method that attempts to create a new <code>LockInfo</code>
680
* from the supplied string which is expected to be a valid representation
681
* of a lock as described in {@link LockInfo#toString()}.
682
*
683
* @param lockString
684
* string value representing a lock
685
* @return if possible, a new <code>LockInfo</code> object initialized
686
* from the data supplied in <code>lockString</code>. If
687
* <code>lockString</code> is <code>null</code> or else is not
688
* in the expected format then this method will return
689
* <code>null</code>.
690
*/
691
private static LockInfo createLockInfoFromLockName(String lockString) {
692
LockInfo result = null;
693
694
if (lockString != null && lockString.length() > 0) {
695
// Expected format is :
696
// <f.q. class name of lock>@<lock identity hash code as hex string>
697
StringTokenizer strTok = new StringTokenizer(lockString, "@"); //$NON-NLS-1$
698
if (strTok.countTokens() == 2) {
699
try {
700
result = new LockInfo(strTok.nextToken(), Integer.parseInt(strTok.nextToken(), 16));
701
} catch (NumberFormatException e) {
702
// ignore and move on - the lockString is not in the correct format
703
}
704
}
705
}
706
return result;
707
}
708
709
}
710
711