8198253: ThreadInfo.from(CompositeData) incorrectly accepts CompositeData with missing JDK 6 attributes
Reviewed-by: dfuchs, jmanson
This commit is contained in:
parent
dc42a2bab5
commit
3414903aba
src/java.management/share/classes
java/lang/management
sun/management
test/jdk
java/lang/management/CompositeData
sun/management/StackTraceElementCompositeData
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -116,11 +116,10 @@ public class MonitorInfo extends LockInfo {
|
||||
* <tbody style="text-align:left">
|
||||
* <tr>
|
||||
* <th scope="row">lockedStackFrame</th>
|
||||
* <td><code>CompositeData as specified in the
|
||||
* <a href="ThreadInfo.html#StackTrace">stackTrace</a>
|
||||
* attribute defined in the {@link ThreadInfo#from
|
||||
* ThreadInfo.from} method.
|
||||
* </code></td>
|
||||
* <td><a href="ThreadInfo.html#stackTraceElement">
|
||||
* {@code CompositeData} for {@code StackTraceElement}</a> as specified
|
||||
* in {@link ThreadInfo#from(CompositeData)} method.
|
||||
* </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockedStackDepth</th>
|
||||
@ -134,7 +133,7 @@ public class MonitorInfo extends LockInfo {
|
||||
* @throws IllegalArgumentException if {@code cd} does not
|
||||
* represent a {@code MonitorInfo} with the attributes described
|
||||
* above.
|
||||
|
||||
*
|
||||
* @return a {@code MonitorInfo} object represented
|
||||
* by {@code cd} if {@code cd} is not {@code null};
|
||||
* {@code null} otherwise.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,6 +25,7 @@
|
||||
|
||||
package java.lang.management;
|
||||
|
||||
import javax.management.openmbean.ArrayType;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import sun.management.ManagementFactoryHelper;
|
||||
import sun.management.ThreadInfoCompositeData;
|
||||
@ -110,7 +111,6 @@ public class ThreadInfo {
|
||||
private StackTraceElement[] stackTrace;
|
||||
private MonitorInfo[] lockedMonitors;
|
||||
private LockInfo[] lockedSynchronizers;
|
||||
|
||||
private static MonitorInfo[] EMPTY_MONITORS = new MonitorInfo[0];
|
||||
private static LockInfo[] EMPTY_SYNCS = new LockInfo[0];
|
||||
|
||||
@ -264,6 +264,11 @@ public class ThreadInfo {
|
||||
/*
|
||||
* Constructs a {@code ThreadInfo} object from a
|
||||
* {@link CompositeData CompositeData}.
|
||||
*
|
||||
* @throws IllegalArgumentException if the given CompositeData does not
|
||||
* contain all of the attributes defined for ThreadInfo of version <= N.
|
||||
*
|
||||
* @see ThreadInfo#from
|
||||
*/
|
||||
private ThreadInfo(CompositeData cd) {
|
||||
ThreadInfoCompositeData ticd = ThreadInfoCompositeData.getInstance(cd);
|
||||
@ -281,41 +286,11 @@ public class ThreadInfo {
|
||||
suspended = ticd.suspended();
|
||||
inNative = ticd.inNative();
|
||||
stackTrace = ticd.stackTrace();
|
||||
|
||||
// 6.0 attributes
|
||||
if (ticd.hasV6()) {
|
||||
lock = ticd.lockInfo();
|
||||
lockedMonitors = ticd.lockedMonitors();
|
||||
lockedSynchronizers = ticd.lockedSynchronizers();
|
||||
} else {
|
||||
// lockInfo is a new attribute added in 1.6 ThreadInfo
|
||||
// If cd is a 5.0 version, construct the LockInfo object
|
||||
// from the lockName value.
|
||||
if (lockName != null) {
|
||||
String result[] = lockName.split("@");
|
||||
if (result.length == 2) {
|
||||
int identityHashCode = Integer.parseInt(result[1], 16);
|
||||
lock = new LockInfo(result[0], identityHashCode);
|
||||
} else {
|
||||
assert result.length == 2;
|
||||
lock = null;
|
||||
}
|
||||
} else {
|
||||
lock = null;
|
||||
}
|
||||
lockedMonitors = EMPTY_MONITORS;
|
||||
lockedSynchronizers = EMPTY_SYNCS;
|
||||
}
|
||||
|
||||
// 9.0 attributes
|
||||
if (ticd.isCurrentVersion()) {
|
||||
daemon = ticd.isDaemon();
|
||||
priority = ticd.getPriority();
|
||||
} else {
|
||||
// Not ideal, but unclear what else we can do.
|
||||
daemon = false;
|
||||
priority = Thread.NORM_PRIORITY;
|
||||
}
|
||||
lock = ticd.lockInfo();
|
||||
lockedMonitors = ticd.lockedMonitors();
|
||||
lockedSynchronizers = ticd.lockedSynchronizers();
|
||||
daemon = ticd.isDaemon();
|
||||
priority = ticd.getPriority();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,52 +667,105 @@ public class ThreadInfo {
|
||||
/**
|
||||
* Returns a {@code ThreadInfo} object represented by the
|
||||
* given {@code CompositeData}.
|
||||
* The given {@code CompositeData} must contain the following attributes
|
||||
* unless otherwise specified below:
|
||||
*
|
||||
* <a id="attributes"></a>
|
||||
* A {@code CompositeData} representing a {@code ThreadInfo} of
|
||||
* version <em>N</em> must contain all of the attributes defined
|
||||
* in version ≤ <em>N</em> unless specified otherwise.
|
||||
* The same rule applies the composite type of the given
|
||||
* {@code CompositeData} and transitively to attributes whose
|
||||
* {@linkplain CompositeData#getCompositeType() type} or
|
||||
* {@linkplain ArrayType#getElementOpenType() component type} is
|
||||
* {@code CompositeType}.
|
||||
* <p>
|
||||
* A {@code CompositeData} representing {@code ThreadInfo} of
|
||||
* version <em>N</em> contains {@code "stackTrace"} attribute and
|
||||
* {@code "lockedMonitors"} attribute representing
|
||||
* an array of {@code StackTraceElement} and
|
||||
* an array of {@link MonitorInfo} respectively
|
||||
* and their types are of version <em>N</em>.
|
||||
* The {@code "lockedStackFrame"} attribute in
|
||||
* {@link MonitorInfo#from(CompositeData) MonitorInfo}'s composite type
|
||||
* must represent {@code StackTraceElement} of the same version <em>N</em>.
|
||||
* Otherwise, this method will throw {@code IllegalArgumentException}.
|
||||
*
|
||||
* <table class="striped" style="margin-left:2em">
|
||||
* <caption style="display:none">The attributes and their types the given CompositeData contains</caption>
|
||||
* <caption style="display:none">The attributes and their types for ThreadInfo's composite data</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col">Attribute Name</th>
|
||||
* <th scope="col">Type</th>
|
||||
* <th scope="col">Since</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr>
|
||||
* <th scope="row">threadId</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">threadName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">threadState</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">suspended</th>
|
||||
* <td>{@code java.lang.Boolean}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">inNative</th>
|
||||
* <td>{@code java.lang.Boolean}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">blockedCount</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">blockedTime</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">waitedCount</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">waitedTime</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockOwnerId</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockOwnerName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row"><a id="StackTrace">stackTrace</a></th>
|
||||
* <td>{@code javax.management.openmbean.CompositeData[]}, each element
|
||||
* is a {@code CompositeData} representing {@code StackTraceElement}
|
||||
* as specified <a href="#stackTraceElement">below</a>.
|
||||
* </td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockInfo</th>
|
||||
@ -745,78 +773,21 @@ public class ThreadInfo {
|
||||
* - the mapped type for {@link LockInfo} as specified in the
|
||||
* {@link LockInfo#from} method.
|
||||
* <p>
|
||||
* If {@code cd} does not contain this attribute,
|
||||
* If the given {@code CompositeData} does not contain this attribute,
|
||||
* the {@code LockInfo} object will be constructed from
|
||||
* the value of the {@code lockName} attribute. </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockOwnerId</th>
|
||||
* <td>{@code java.lang.Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockOwnerName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row"><a id="StackTrace">stackTrace</a></th>
|
||||
* <td>{@code javax.management.openmbean.CompositeData[]}
|
||||
* <p>
|
||||
* Each element is a {@code CompositeData} representing
|
||||
* StackTraceElement containing the following attributes:
|
||||
* <table class="striped" style="margin-left:2em">
|
||||
* <caption style="display:none">The attributes and their types the given CompositeData contains</caption>
|
||||
* <thead style="text-align:center">
|
||||
* <tr>
|
||||
* <th scope="col">Attribute Name</th>
|
||||
* <th scope="col">Type</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr>
|
||||
* <th scope="row">moduleName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">moduleVersion</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">className</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">methodName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">fileName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lineNumber</th>
|
||||
* <td>{@code java.lang.Integer}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">nativeMethod</th>
|
||||
* <td>{@code java.lang.Boolean}</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* </td>
|
||||
* the value of the {@code lockName} attribute.</td>
|
||||
* <td>6</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockedMonitors</th>
|
||||
* <td>{@code javax.management.openmbean.CompositeData[]}
|
||||
* whose element type is the mapped type for
|
||||
* {@link MonitorInfo} as specified in the
|
||||
* {@link MonitorInfo#from Monitor.from} method.
|
||||
* {@link MonitorInfo#from MonitorInfo.from} method.
|
||||
* <p>
|
||||
* If {@code cd} does not contain this attribute,
|
||||
* this attribute will be set to an empty array. </td>
|
||||
* If the given {@code CompositeData} does not contain this attribute,
|
||||
* this attribute will be set to an empty array.</td>
|
||||
* <td>6</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lockedSynchronizers</th>
|
||||
@ -824,25 +795,93 @@ public class ThreadInfo {
|
||||
* whose element type is the mapped type for
|
||||
* {@link LockInfo} as specified in the {@link LockInfo#from} method.
|
||||
* <p>
|
||||
* If {@code cd} does not contain this attribute,
|
||||
* this attribute will be set to an empty array. </td>
|
||||
* If the given {@code CompositeData} does not contain this attribute,
|
||||
* this attribute will be set to an empty array.</td>
|
||||
* <td>6</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">daemon</th>
|
||||
* <td>{@code java.lang.Boolean}</td>
|
||||
* <td>{@code java.lang.Boolean}
|
||||
* <p>
|
||||
* If the given {@code CompositeData} does not contain this attribute,
|
||||
* this attribute will be set to {@code false}.</td>
|
||||
* <td>9</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">priority</th>
|
||||
* <td>{@code java.lang.Integer}
|
||||
* <p>
|
||||
* If the given {@code CompositeData} does not contain this attribute,
|
||||
* This attribute will be set to {@link Thread#NORM_PRIORITY}.</td>
|
||||
* <td>9</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* <a id="stackTraceElement">A {@code CompositeData} representing
|
||||
* {@code StackTraceElement}</a> of version <em>N</em> must contain
|
||||
* all of the attributes defined in version ≤ <em>N</em>
|
||||
* unless specified otherwise.
|
||||
*
|
||||
* <table class="striped" style="margin-left:2em">
|
||||
* <caption style="display:none">The attributes and their types for StackTraceElement's composite data</caption>
|
||||
* <thead style="text-align:center">
|
||||
* <tr>
|
||||
* <th scope="col">Attribute Name</th>
|
||||
* <th scope="col">Type</th>
|
||||
* <th scope="col">Since</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody style="text-align:left">
|
||||
* <tr>
|
||||
* <th scope="row">classLoaderName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>9</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">moduleName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>9</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">moduleVersion</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>9</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">className</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">methodName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">fileName</th>
|
||||
* <td>{@code java.lang.String}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">lineNumber</th>
|
||||
* <td>{@code java.lang.Integer}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">nativeMethod</th>
|
||||
* <td>{@code java.lang.Boolean}</td>
|
||||
* <td>5</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* @param cd {@code CompositeData} representing a {@code ThreadInfo}
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code cd} does not
|
||||
* represent a {@code ThreadInfo} with the attributes described
|
||||
* above.
|
||||
* @throws IllegalArgumentException if the given {@code cd} and
|
||||
* its composite type does not contain all of
|
||||
* <a href="#attributes">the attributes</a> defined for a
|
||||
* {@code ThreadInfo} of a specific runtime version.
|
||||
*
|
||||
* @return a {@code ThreadInfo} object represented
|
||||
* by {@code cd} if {@code cd} is not {@code null};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -58,15 +58,15 @@ public class LockInfoCompositeData extends LazyCompositeData {
|
||||
|
||||
protected CompositeData getCompositeData() {
|
||||
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
|
||||
// lockInfoItemNames!
|
||||
// LOCK_INFO_ATTRIBUTES!
|
||||
final Object[] lockInfoItemValues = {
|
||||
new String(lock.getClassName()),
|
||||
lock.getIdentityHashCode(),
|
||||
};
|
||||
|
||||
try {
|
||||
return new CompositeDataSupport(lockInfoCompositeType,
|
||||
lockInfoItemNames,
|
||||
return new CompositeDataSupport(LOCK_INFO_COMPOSITE_TYPE,
|
||||
LOCK_INFO_ATTRIBUTES,
|
||||
lockInfoItemValues);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
@ -74,10 +74,10 @@ public class LockInfoCompositeData extends LazyCompositeData {
|
||||
}
|
||||
}
|
||||
|
||||
private static final CompositeType lockInfoCompositeType;
|
||||
private static final CompositeType LOCK_INFO_COMPOSITE_TYPE;
|
||||
static {
|
||||
try {
|
||||
lockInfoCompositeType = (CompositeType)
|
||||
LOCK_INFO_COMPOSITE_TYPE = (CompositeType)
|
||||
MappedMXBeanType.toOpenType(LockInfo.class);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
@ -85,13 +85,13 @@ public class LockInfoCompositeData extends LazyCompositeData {
|
||||
}
|
||||
}
|
||||
|
||||
static CompositeType getLockInfoCompositeType() {
|
||||
return lockInfoCompositeType;
|
||||
static CompositeType compositeType() {
|
||||
return LOCK_INFO_COMPOSITE_TYPE;
|
||||
}
|
||||
|
||||
private static final String CLASS_NAME = "className";
|
||||
private static final String IDENTITY_HASH_CODE = "identityHashCode";
|
||||
private static final String[] lockInfoItemNames = {
|
||||
private static final String[] LOCK_INFO_ATTRIBUTES = {
|
||||
CLASS_NAME,
|
||||
IDENTITY_HASH_CODE,
|
||||
};
|
||||
@ -104,7 +104,7 @@ public class LockInfoCompositeData extends LazyCompositeData {
|
||||
throw new NullPointerException("Null CompositeData");
|
||||
}
|
||||
|
||||
if (!isTypeMatched(lockInfoCompositeType, cd.getCompositeType())) {
|
||||
if (!isTypeMatched(LOCK_INFO_COMPOSITE_TYPE, cd.getCompositeType())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for LockInfo");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -30,7 +30,7 @@ import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.CompositeDataSupport;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
import java.util.Set;
|
||||
import javax.management.openmbean.OpenType;
|
||||
|
||||
/**
|
||||
* A CompositeData for MonitorInfo for the local management support.
|
||||
@ -55,14 +55,14 @@ public class MonitorInfoCompositeData extends LazyCompositeData {
|
||||
|
||||
protected CompositeData getCompositeData() {
|
||||
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
|
||||
// monitorInfoItemNames!
|
||||
// MONITOR_INFO_ATTRIBUTES!
|
||||
|
||||
int len = monitorInfoItemNames.length;
|
||||
int len = MONITOR_INFO_ATTRIBUTES.length;
|
||||
Object[] values = new Object[len];
|
||||
CompositeData li = LockInfoCompositeData.toCompositeData(lock);
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
String item = monitorInfoItemNames[i];
|
||||
String item = MONITOR_INFO_ATTRIBUTES[i];
|
||||
if (item.equals(LOCKED_STACK_FRAME)) {
|
||||
StackTraceElement ste = lock.getLockedStackFrame();
|
||||
values[i] = (ste != null ? StackTraceElementCompositeData.
|
||||
@ -76,8 +76,8 @@ public class MonitorInfoCompositeData extends LazyCompositeData {
|
||||
}
|
||||
|
||||
try {
|
||||
return new CompositeDataSupport(monitorInfoCompositeType,
|
||||
monitorInfoItemNames,
|
||||
return new CompositeDataSupport(MONITOR_INFO_COMPOSITE_TYPE,
|
||||
MONITOR_INFO_ATTRIBUTES,
|
||||
values);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
@ -85,28 +85,50 @@ public class MonitorInfoCompositeData extends LazyCompositeData {
|
||||
}
|
||||
}
|
||||
|
||||
private static final CompositeType monitorInfoCompositeType;
|
||||
private static final String[] monitorInfoItemNames;
|
||||
private static final String CLASS_NAME = "className";
|
||||
private static final String IDENTITY_HASH_CODE = "identityHashCode";
|
||||
private static final String LOCKED_STACK_FRAME = "lockedStackFrame";
|
||||
private static final String LOCKED_STACK_DEPTH = "lockedStackDepth";
|
||||
|
||||
private static final String[] MONITOR_INFO_ATTRIBUTES = {
|
||||
CLASS_NAME,
|
||||
IDENTITY_HASH_CODE,
|
||||
LOCKED_STACK_FRAME,
|
||||
LOCKED_STACK_DEPTH
|
||||
};
|
||||
|
||||
private static final CompositeType MONITOR_INFO_COMPOSITE_TYPE;
|
||||
private static final CompositeType V6_COMPOSITE_TYPE;
|
||||
static {
|
||||
try {
|
||||
monitorInfoCompositeType = (CompositeType)
|
||||
MONITOR_INFO_COMPOSITE_TYPE = (CompositeType)
|
||||
MappedMXBeanType.toOpenType(MonitorInfo.class);
|
||||
Set<String> s = monitorInfoCompositeType.keySet();
|
||||
monitorInfoItemNames = s.toArray(new String[0]);
|
||||
|
||||
OpenType<?>[] types = new OpenType<?>[MONITOR_INFO_ATTRIBUTES.length];
|
||||
for (int i = 0; i < MONITOR_INFO_ATTRIBUTES.length; i++) {
|
||||
String name = MONITOR_INFO_ATTRIBUTES[i];
|
||||
types[i] = name.equals(LOCKED_STACK_FRAME)
|
||||
? StackTraceElementCompositeData.v5CompositeType()
|
||||
: MONITOR_INFO_COMPOSITE_TYPE.getType(name);
|
||||
}
|
||||
V6_COMPOSITE_TYPE = new CompositeType("MonitorInfo",
|
||||
"JDK 6 MonitorInfo",
|
||||
MONITOR_INFO_ATTRIBUTES,
|
||||
MONITOR_INFO_ATTRIBUTES,
|
||||
types);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static CompositeType getMonitorInfoCompositeType() {
|
||||
return monitorInfoCompositeType;
|
||||
static CompositeType v6CompositeType() {
|
||||
return V6_COMPOSITE_TYPE;
|
||||
}
|
||||
|
||||
private static final String CLASS_NAME = "className";
|
||||
private static final String IDENTITY_HASH_CODE = "identityHashCode";
|
||||
private static final String LOCKED_STACK_FRAME = "lockedStackFrame";
|
||||
private static final String LOCKED_STACK_DEPTH = "lockedStackDepth";
|
||||
static CompositeType compositeType() {
|
||||
return MONITOR_INFO_COMPOSITE_TYPE;
|
||||
}
|
||||
|
||||
public static String getClassName(CompositeData cd) {
|
||||
return getString(cd, CLASS_NAME);
|
||||
@ -138,7 +160,8 @@ public class MonitorInfoCompositeData extends LazyCompositeData {
|
||||
throw new NullPointerException("Null CompositeData");
|
||||
}
|
||||
|
||||
if (!isTypeMatched(monitorInfoCompositeType, cd.getCompositeType())) {
|
||||
if (!isTypeMatched(MONITOR_INFO_COMPOSITE_TYPE, cd.getCompositeType()) &&
|
||||
!isTypeMatched(V6_COMPOSITE_TYPE, cd.getCompositeType())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for MonitorInfo");
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,13 +25,13 @@
|
||||
|
||||
package sun.management;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.CompositeDataSupport;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
import javax.management.openmbean.OpenType;
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A CompositeData for StackTraceElement for the local management support.
|
||||
@ -52,12 +52,7 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
public static StackTraceElement from(CompositeData cd) {
|
||||
validateCompositeData(cd);
|
||||
|
||||
if (stackTraceElementV6CompositeType.equals(cd.getCompositeType())) {
|
||||
return new StackTraceElement(getString(cd, CLASS_NAME),
|
||||
getString(cd, METHOD_NAME),
|
||||
getString(cd, FILE_NAME),
|
||||
getInt(cd, LINE_NUMBER));
|
||||
} else {
|
||||
if (STACK_TRACE_ELEMENT_COMPOSITE_TYPE.equals(cd.getCompositeType())) {
|
||||
return new StackTraceElement(getString(cd, CLASS_LOADER_NAME),
|
||||
getString(cd, MODULE_NAME),
|
||||
getString(cd, MODULE_VERSION),
|
||||
@ -65,6 +60,12 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
getString(cd, METHOD_NAME),
|
||||
getString(cd, FILE_NAME),
|
||||
getInt(cd, LINE_NUMBER));
|
||||
} else {
|
||||
return new StackTraceElement(getString(cd, CLASS_NAME),
|
||||
getString(cd, METHOD_NAME),
|
||||
getString(cd, FILE_NAME),
|
||||
getInt(cd, LINE_NUMBER));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -75,7 +76,7 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
|
||||
protected CompositeData getCompositeData() {
|
||||
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
|
||||
// stackTraceElementItemNames!
|
||||
// STACK_TRACE_ELEMENT_ATTRIBUTES!
|
||||
final Object[] stackTraceElementItemValues = {
|
||||
ste.getClassLoaderName(),
|
||||
ste.getModuleName(),
|
||||
@ -87,8 +88,8 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
ste.isNativeMethod(),
|
||||
};
|
||||
try {
|
||||
return new CompositeDataSupport(stackTraceElementCompositeType,
|
||||
stackTraceElementItemNames,
|
||||
return new CompositeDataSupport(STACK_TRACE_ELEMENT_COMPOSITE_TYPE,
|
||||
STACK_TRACE_ELEMENT_ATTRIBUTES,
|
||||
stackTraceElementItemValues);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
@ -106,11 +107,7 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
private static final String LINE_NUMBER = "lineNumber";
|
||||
private static final String NATIVE_METHOD = "nativeMethod";
|
||||
|
||||
|
||||
private static final String[] stackTraceElementItemNames = {
|
||||
CLASS_LOADER_NAME,
|
||||
MODULE_NAME,
|
||||
MODULE_VERSION,
|
||||
private static final String[] V5_ATTRIBUTES = {
|
||||
CLASS_NAME,
|
||||
METHOD_NAME,
|
||||
FILE_NAME,
|
||||
@ -118,30 +115,48 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
NATIVE_METHOD,
|
||||
};
|
||||
|
||||
private static final String[] stackTraceElementV9ItemNames = {
|
||||
private static final String[] V9_ATTRIBUTES = {
|
||||
CLASS_LOADER_NAME,
|
||||
MODULE_NAME,
|
||||
MODULE_VERSION,
|
||||
};
|
||||
|
||||
private static final CompositeType stackTraceElementCompositeType;
|
||||
private static final CompositeType stackTraceElementV6CompositeType;
|
||||
private static final String[] STACK_TRACE_ELEMENT_ATTRIBUTES =
|
||||
Stream.of(V5_ATTRIBUTES, V9_ATTRIBUTES).flatMap(Arrays::stream)
|
||||
.toArray(String[]::new);
|
||||
|
||||
private static final CompositeType STACK_TRACE_ELEMENT_COMPOSITE_TYPE;
|
||||
private static final CompositeType V5_COMPOSITE_TYPE;
|
||||
static {
|
||||
try {
|
||||
stackTraceElementCompositeType = (CompositeType)
|
||||
STACK_TRACE_ELEMENT_COMPOSITE_TYPE = (CompositeType)
|
||||
MappedMXBeanType.toOpenType(StackTraceElement.class);
|
||||
stackTraceElementV6CompositeType =
|
||||
TypeVersionMapper.getInstance().getVersionedCompositeType(
|
||||
stackTraceElementCompositeType,
|
||||
TypeVersionMapper.V6
|
||||
);
|
||||
|
||||
OpenType<?>[] types = new OpenType<?>[V5_ATTRIBUTES.length];
|
||||
for (int i=0; i < V5_ATTRIBUTES.length; i++) {
|
||||
String name = V5_ATTRIBUTES[i];
|
||||
types[i] = STACK_TRACE_ELEMENT_COMPOSITE_TYPE.getType(name);
|
||||
}
|
||||
V5_COMPOSITE_TYPE = new CompositeType("StackTraceElement",
|
||||
"JDK 5 StackTraceElement",
|
||||
V5_ATTRIBUTES,
|
||||
V5_ATTRIBUTES,
|
||||
types);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Validate if the input CompositeData has the expected
|
||||
static CompositeType v5CompositeType() {
|
||||
return V5_COMPOSITE_TYPE;
|
||||
}
|
||||
static CompositeType compositeType() {
|
||||
return STACK_TRACE_ELEMENT_COMPOSITE_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate if the input CompositeData has the expected
|
||||
* CompositeType (i.e. contain all attributes with expected
|
||||
* names and types).
|
||||
*/
|
||||
@ -151,22 +166,11 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
|
||||
}
|
||||
|
||||
CompositeType ct = cd.getCompositeType();
|
||||
if (!isTypeMatched(stackTraceElementCompositeType, ct)) {
|
||||
if (!isTypeMatched(stackTraceElementV6CompositeType, ct)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for StackTraceElement");
|
||||
}
|
||||
if (!isTypeMatched(STACK_TRACE_ELEMENT_COMPOSITE_TYPE, ct) &&
|
||||
!isTypeMatched(V5_COMPOSITE_TYPE, ct)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for StackTraceElement");
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isV6Attribute(String name) {
|
||||
for(String attrName : stackTraceElementV9ItemNames) {
|
||||
if (name.equals(attrName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -2704607706598396827L;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,10 +28,16 @@ package sun.management;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.lang.management.MonitorInfo;
|
||||
import java.lang.management.LockInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
import javax.management.openmbean.ArrayType;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.CompositeDataSupport;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
import javax.management.openmbean.OpenType;
|
||||
|
||||
/**
|
||||
* A CompositeData for ThreadInfo for the local management support.
|
||||
@ -41,35 +47,21 @@ import javax.management.openmbean.OpenDataException;
|
||||
public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
private final ThreadInfo threadInfo;
|
||||
private final CompositeData cdata;
|
||||
private final boolean currentVersion;
|
||||
private final boolean hasV6;
|
||||
|
||||
private ThreadInfoCompositeData(ThreadInfo ti) {
|
||||
this.threadInfo = ti;
|
||||
this.currentVersion = true;
|
||||
this.cdata = null;
|
||||
this.hasV6 = true;
|
||||
}
|
||||
|
||||
private ThreadInfoCompositeData(CompositeData cd) {
|
||||
this.threadInfo = null;
|
||||
this.currentVersion = ThreadInfoCompositeData.isCurrentVersion(cd);
|
||||
this.cdata = cd;
|
||||
this.hasV6 = ThreadInfoCompositeData.hasV6(cd);
|
||||
}
|
||||
|
||||
public ThreadInfo getThreadInfo() {
|
||||
return threadInfo;
|
||||
}
|
||||
|
||||
public boolean hasV6() {
|
||||
return hasV6;
|
||||
}
|
||||
|
||||
public boolean isCurrentVersion() {
|
||||
return currentVersion;
|
||||
}
|
||||
|
||||
public static ThreadInfoCompositeData getInstance(CompositeData cd) {
|
||||
validateCompositeData(cd);
|
||||
return new ThreadInfoCompositeData(cd);
|
||||
@ -112,7 +104,7 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
}
|
||||
|
||||
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
|
||||
// threadInfoItemNames!
|
||||
// THREAD_INFO_ATTRIBUTES!
|
||||
final Object[] threadInfoItemValues = {
|
||||
threadInfo.getThreadId(),
|
||||
threadInfo.getThreadName(),
|
||||
@ -126,8 +118,8 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
threadInfo.getLockOwnerId(),
|
||||
threadInfo.getLockOwnerName(),
|
||||
stackTraceData,
|
||||
threadInfo.isSuspended(),
|
||||
threadInfo.isInNative(),
|
||||
threadInfo.isSuspended(),
|
||||
threadInfo.isInNative(),
|
||||
lockedMonitorsData,
|
||||
lockedSyncsData,
|
||||
threadInfo.isDaemon(),
|
||||
@ -135,8 +127,8 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
};
|
||||
|
||||
try {
|
||||
return new CompositeDataSupport(threadInfoCompositeType,
|
||||
threadInfoItemNames,
|
||||
return new CompositeDataSupport(compositeType(),
|
||||
THREAD_INFO_ATTRIBTUES,
|
||||
threadInfoItemValues);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
@ -164,7 +156,7 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
private static final String LOCKED_MONITORS = "lockedMonitors";
|
||||
private static final String LOCKED_SYNCS = "lockedSynchronizers";
|
||||
|
||||
private static final String[] threadInfoItemNames = {
|
||||
private static final String[] V5_ATTRIBUTES = {
|
||||
THREAD_ID,
|
||||
THREAD_NAME,
|
||||
THREAD_STATE,
|
||||
@ -172,109 +164,28 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
BLOCKED_COUNT,
|
||||
WAITED_TIME,
|
||||
WAITED_COUNT,
|
||||
LOCK_INFO,
|
||||
LOCK_NAME,
|
||||
LOCK_OWNER_ID,
|
||||
LOCK_OWNER_NAME,
|
||||
STACK_TRACE,
|
||||
SUSPENDED,
|
||||
IN_NATIVE,
|
||||
LOCKED_MONITORS,
|
||||
LOCKED_SYNCS,
|
||||
DAEMON,
|
||||
PRIORITY,
|
||||
IN_NATIVE
|
||||
};
|
||||
|
||||
// New attributes added in 6.0 ThreadInfo
|
||||
private static final String[] threadInfoV6Attributes = {
|
||||
private static final String[] V6_ATTRIBUTES = {
|
||||
LOCK_INFO,
|
||||
LOCKED_MONITORS,
|
||||
LOCKED_SYNCS,
|
||||
};
|
||||
|
||||
private static final String[] threadInfoV9Attributes = {
|
||||
private static final String[] V9_ATTRIBUTES = {
|
||||
DAEMON,
|
||||
PRIORITY,
|
||||
};
|
||||
|
||||
// Current version of ThreadInfo
|
||||
private static final CompositeType threadInfoCompositeType;
|
||||
// Previous version of ThreadInfo
|
||||
private static final CompositeType threadInfoV6CompositeType;
|
||||
// Previous-previous version of ThreadInfo
|
||||
private static final CompositeType threadInfoV5CompositeType;
|
||||
private static final CompositeType lockInfoCompositeType;
|
||||
static {
|
||||
try {
|
||||
threadInfoCompositeType = (CompositeType)
|
||||
MappedMXBeanType.toOpenType(ThreadInfo.class);
|
||||
// Form a CompositeType for JDK 5.0 ThreadInfo version
|
||||
|
||||
threadInfoV5CompositeType =
|
||||
TypeVersionMapper.getInstance().getVersionedCompositeType(
|
||||
threadInfoCompositeType, TypeVersionMapper.V5
|
||||
);
|
||||
|
||||
threadInfoV6CompositeType =
|
||||
TypeVersionMapper.getInstance().getVersionedCompositeType(
|
||||
threadInfoCompositeType, TypeVersionMapper.V6
|
||||
);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
|
||||
// Each CompositeData object has its CompositeType associated
|
||||
// with it. So we can get the CompositeType representing LockInfo
|
||||
// from a mapped CompositeData for any LockInfo object.
|
||||
// Thus we construct a random LockInfo object and pass it
|
||||
// to LockInfoCompositeData to do the conversion.
|
||||
Object o = new Object();
|
||||
LockInfo li = new LockInfo(o.getClass().getName(),
|
||||
System.identityHashCode(o));
|
||||
CompositeData cd = LockInfoCompositeData.toCompositeData(li);
|
||||
lockInfoCompositeType = cd.getCompositeType();
|
||||
}
|
||||
|
||||
static boolean isV5Attribute(String itemName) {
|
||||
for (String n : threadInfoV6Attributes) {
|
||||
if (itemName.equals(n)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (String n : threadInfoV9Attributes) {
|
||||
if (itemName.equals(n)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean isV6Attribute(String itemName) {
|
||||
for (String n : threadInfoV9Attributes) {
|
||||
if (itemName.equals(n)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isCurrentVersion(CompositeData cd) {
|
||||
if (cd == null) {
|
||||
throw new NullPointerException("Null CompositeData");
|
||||
}
|
||||
|
||||
return isTypeMatched(threadInfoCompositeType, cd.getCompositeType());
|
||||
}
|
||||
|
||||
private static boolean hasV6(CompositeData cd) {
|
||||
if (cd == null) {
|
||||
throw new NullPointerException("Null CompositeData");
|
||||
}
|
||||
|
||||
return isTypeMatched(threadInfoCompositeType, cd.getCompositeType()) ||
|
||||
isTypeMatched(threadInfoV6CompositeType, cd.getCompositeType());
|
||||
}
|
||||
private static final String[] THREAD_INFO_ATTRIBTUES =
|
||||
Stream.of(V5_ATTRIBUTES, V6_ATTRIBUTES, V9_ATTRIBUTES)
|
||||
.flatMap(Arrays::stream).toArray(String[]::new);
|
||||
|
||||
public long threadId() {
|
||||
return getLong(cdata, THREAD_ID);
|
||||
@ -333,12 +244,18 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
return getBoolean(cdata, IN_NATIVE);
|
||||
}
|
||||
|
||||
/*
|
||||
* if daemon attribute is not present, default to false.
|
||||
*/
|
||||
public boolean isDaemon() {
|
||||
return getBoolean(cdata, DAEMON);
|
||||
return cdata.containsKey(DAEMON) ? getBoolean(cdata, DAEMON) : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* if priority attribute is not present, default to norm priority.
|
||||
*/
|
||||
public int getPriority(){
|
||||
return getInt(cdata, PRIORITY);
|
||||
return cdata.containsKey(PRIORITY) ? getInt(cdata, PRIORITY) : Thread.NORM_PRIORITY;
|
||||
}
|
||||
|
||||
public StackTraceElement[] stackTrace() {
|
||||
@ -356,13 +273,37 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
return stackTrace;
|
||||
}
|
||||
|
||||
// 6.0 new attributes
|
||||
/*
|
||||
* lockInfo is a new attribute added in JDK 6 ThreadInfo
|
||||
* If cd is a 5.0 version, construct the LockInfo object
|
||||
* from the lockName value.
|
||||
*/
|
||||
public LockInfo lockInfo() {
|
||||
CompositeData lockInfoData = (CompositeData) cdata.get(LOCK_INFO);
|
||||
return LockInfo.from(lockInfoData);
|
||||
if (cdata.containsKey(LOCK_INFO)) {
|
||||
CompositeData lockInfoData = (CompositeData) cdata.get(LOCK_INFO);
|
||||
return LockInfo.from(lockInfoData);
|
||||
} else {
|
||||
String lockName = lockName();
|
||||
LockInfo lock = null;
|
||||
if (lockName != null) {
|
||||
String result[] = lockName.split("@");
|
||||
if (result.length == 2) {
|
||||
int identityHashCode = Integer.parseInt(result[1], 16);
|
||||
lock = new LockInfo(result[0], identityHashCode);
|
||||
}
|
||||
}
|
||||
return lock;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty array if locked_monitors attribute is not present.
|
||||
*/
|
||||
public MonitorInfo[] lockedMonitors() {
|
||||
if (!cdata.containsKey(LOCKED_MONITORS)) {
|
||||
return new MonitorInfo[0];
|
||||
}
|
||||
|
||||
CompositeData[] lockedMonitorsData =
|
||||
(CompositeData[]) cdata.get(LOCKED_MONITORS);
|
||||
|
||||
@ -377,7 +318,14 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
return monitors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an empty array if locked_monitors attribute is not present.
|
||||
*/
|
||||
public LockInfo[] lockedSynchronizers() {
|
||||
if (!cdata.containsKey(LOCKED_SYNCS)) {
|
||||
return new LockInfo[0];
|
||||
}
|
||||
|
||||
CompositeData[] lockedSyncsData =
|
||||
(CompositeData[]) cdata.get(LOCKED_SYNCS);
|
||||
|
||||
@ -391,7 +339,8 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
return locks;
|
||||
}
|
||||
|
||||
/** Validate if the input CompositeData has the expected
|
||||
/**
|
||||
* Validate if the input CompositeData has the expected
|
||||
* CompositeType (i.e. contain all attributes with expected
|
||||
* names and types).
|
||||
*/
|
||||
@ -401,62 +350,98 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
|
||||
}
|
||||
|
||||
CompositeType type = cd.getCompositeType();
|
||||
boolean currentVersion = true;
|
||||
if (!isTypeMatched(threadInfoCompositeType, type)) {
|
||||
currentVersion = false;
|
||||
// check if cd is an older version
|
||||
if (!isTypeMatched(threadInfoV5CompositeType, type) &&
|
||||
!isTypeMatched(threadInfoV6CompositeType, type)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for ThreadInfo");
|
||||
}
|
||||
int version;
|
||||
if (Arrays.stream(V9_ATTRIBUTES).anyMatch(type::containsKey)) {
|
||||
version = Runtime.version().feature();
|
||||
} else if (Arrays.stream(V6_ATTRIBUTES).anyMatch(type::containsKey)) {
|
||||
version = 6;
|
||||
} else {
|
||||
version = 5;
|
||||
}
|
||||
|
||||
CompositeData[] stackTraceData =
|
||||
(CompositeData[]) cd.get(STACK_TRACE);
|
||||
if (stackTraceData == null) {
|
||||
if (!isTypeMatched(ThreadInfoCompositeTypes.ofVersion(version), type)) {
|
||||
throw new IllegalArgumentException(
|
||||
"StackTraceElement[] is missing");
|
||||
}
|
||||
if (stackTraceData.length > 0) {
|
||||
StackTraceElementCompositeData.validateCompositeData(stackTraceData[0]);
|
||||
}
|
||||
|
||||
// validate v6 attributes
|
||||
if (currentVersion) {
|
||||
CompositeData li = (CompositeData) cd.get(LOCK_INFO);
|
||||
if (li != null) {
|
||||
if (!isTypeMatched(lockInfoCompositeType,
|
||||
li.getCompositeType())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for \"" +
|
||||
LOCK_INFO + "\" attribute.");
|
||||
}
|
||||
}
|
||||
|
||||
CompositeData[] lms = (CompositeData[]) cd.get(LOCKED_MONITORS);
|
||||
if (lms == null) {
|
||||
throw new IllegalArgumentException("MonitorInfo[] is null");
|
||||
}
|
||||
if (lms.length > 0) {
|
||||
MonitorInfoCompositeData.validateCompositeData(lms[0]);
|
||||
}
|
||||
|
||||
CompositeData[] lsyncs = (CompositeData[]) cd.get(LOCKED_SYNCS);
|
||||
if (lsyncs == null) {
|
||||
throw new IllegalArgumentException("LockInfo[] is null");
|
||||
}
|
||||
if (lsyncs.length > 0) {
|
||||
if (!isTypeMatched(lockInfoCompositeType,
|
||||
lsyncs[0].getCompositeType())) {
|
||||
throw new IllegalArgumentException(
|
||||
"Unexpected composite type for \"" +
|
||||
LOCKED_SYNCS + "\" attribute.");
|
||||
}
|
||||
}
|
||||
|
||||
"Unexpected composite type for ThreadInfo of version " + version);
|
||||
}
|
||||
}
|
||||
|
||||
public static CompositeType compositeType() {
|
||||
return ThreadInfoCompositeTypes.compositeTypes.get(0);
|
||||
}
|
||||
|
||||
static class ThreadInfoCompositeTypes {
|
||||
static final int CURRENT = Runtime.version().feature();
|
||||
static final Map<Integer, CompositeType> compositeTypes = initCompositeTypes();
|
||||
/*
|
||||
* Returns CompositeType of the given runtime version
|
||||
*/
|
||||
static CompositeType ofVersion(int version) {
|
||||
return compositeTypes.get(version);
|
||||
}
|
||||
|
||||
static Map<Integer, CompositeType> initCompositeTypes() {
|
||||
Map<Integer, CompositeType> types = new HashMap<>();
|
||||
CompositeType ctype = initCompositeType();
|
||||
types.put(CURRENT, ctype);
|
||||
types.put(5, initV5CompositeType(ctype));
|
||||
types.put(6, initV6CompositeType(ctype));
|
||||
return types;
|
||||
}
|
||||
|
||||
static CompositeType initCompositeType() {
|
||||
try {
|
||||
return (CompositeType)MappedMXBeanType.toOpenType(ThreadInfo.class);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static CompositeType initV5CompositeType(CompositeType threadInfoCompositeType) {
|
||||
try {
|
||||
OpenType<?>[] v5Types = new OpenType<?>[V5_ATTRIBUTES.length];
|
||||
for (int i = 0; i < v5Types.length; i++) {
|
||||
String name = V5_ATTRIBUTES[i];
|
||||
v5Types[i] = name.equals(STACK_TRACE)
|
||||
? new ArrayType<>(1, StackTraceElementCompositeData.v5CompositeType())
|
||||
: threadInfoCompositeType.getType(name);
|
||||
}
|
||||
return new CompositeType("ThreadInfo",
|
||||
"JDK 5 ThreadInfo",
|
||||
V5_ATTRIBUTES,
|
||||
V5_ATTRIBUTES,
|
||||
v5Types);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
static CompositeType initV6CompositeType(CompositeType threadInfoCompositeType) {
|
||||
try {
|
||||
String[] v6Names = Stream.of(V5_ATTRIBUTES, V6_ATTRIBUTES)
|
||||
.flatMap(Arrays::stream).toArray(String[]::new);
|
||||
OpenType<?>[] v6Types = new OpenType<?>[v6Names.length];
|
||||
for (int i = 0; i < v6Names.length; i++) {
|
||||
String name = v6Names[i];
|
||||
OpenType<?> ot = threadInfoCompositeType.getType(name);
|
||||
if (name.equals(STACK_TRACE)) {
|
||||
ot = new ArrayType<>(1, StackTraceElementCompositeData.v5CompositeType());
|
||||
} else if (name.equals(LOCKED_MONITORS)) {
|
||||
ot = new ArrayType<>(1, MonitorInfoCompositeData.v6CompositeType());
|
||||
}
|
||||
v6Types[i] = ot;
|
||||
}
|
||||
return new CompositeType("ThreadInfo",
|
||||
"JDK 6 ThreadInfo",
|
||||
v6Names,
|
||||
v6Names,
|
||||
v6Types);
|
||||
} catch (OpenDataException e) {
|
||||
// Should never reach here
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
private static final long serialVersionUID = 2464378539119753175L;
|
||||
}
|
||||
|
@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package sun.management;
|
||||
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import javax.management.openmbean.ArrayType;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.OpenDataException;
|
||||
import javax.management.openmbean.OpenType;
|
||||
import javax.management.openmbean.SimpleType;
|
||||
import javax.management.openmbean.TabularType;
|
||||
import static sun.management.Util.toStringArray;
|
||||
|
||||
/**
|
||||
* Provides simplistic support for versioning of {@linkplain CompositeType} instances
|
||||
* based on the latest version and filtering out certain items.
|
||||
*/
|
||||
final class TypeVersionMapper {
|
||||
private static final class Singleton {
|
||||
private final static TypeVersionMapper INSTANCE = new TypeVersionMapper();
|
||||
}
|
||||
|
||||
final static String V5 = "J2SE 5.0";
|
||||
final static String V6 = "Java SE 6";
|
||||
|
||||
private final Map<String, Map<String, Predicate<String>>> filterMap;
|
||||
|
||||
private TypeVersionMapper() {
|
||||
filterMap = new HashMap<>();
|
||||
setupStackTraceElement();
|
||||
setupThreadInfo();
|
||||
}
|
||||
|
||||
public static TypeVersionMapper getInstance() {
|
||||
return Singleton.INSTANCE;
|
||||
}
|
||||
|
||||
private void setupStackTraceElement() {
|
||||
Map<String, Predicate<String>> filter = new HashMap<>();
|
||||
filterMap.put(StackTraceElement.class.getName(), filter);
|
||||
filter.put(V5, StackTraceElementCompositeData::isV6Attribute);
|
||||
filter.put(V6, StackTraceElementCompositeData::isV6Attribute);
|
||||
}
|
||||
|
||||
private void setupThreadInfo() {
|
||||
Map<String, Predicate<String>> filter = new HashMap<>();
|
||||
filterMap.put(ThreadInfo.class.getName(), filter);
|
||||
filter.put(V5, ThreadInfoCompositeData::isV5Attribute);
|
||||
filter.put(V6, ThreadInfoCompositeData::isV6Attribute);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the specified version of a {@linkplain CompositeType} instance.
|
||||
* @param type The current (latest) version of {@linkplain CompositeType}
|
||||
* @param version The version identifier (eg. {@linkplain TypeVersionMapper#V5})
|
||||
* @return Returns the {@linkplain CompositeType} corresponding to the requested
|
||||
* version.
|
||||
* @throws OpenDataException
|
||||
*/
|
||||
CompositeType getVersionedCompositeType(CompositeType type, String version)
|
||||
throws OpenDataException
|
||||
{
|
||||
Predicate<String> filter = getFilter(type.getTypeName(), version);
|
||||
if (filter == null) {
|
||||
return type;
|
||||
}
|
||||
|
||||
List<String> itemNames = new ArrayList<>();
|
||||
List<String> itemDesc = new ArrayList<>();
|
||||
List<OpenType<?>> itemTypes = new ArrayList<>();
|
||||
|
||||
for(String item : type.keySet()) {
|
||||
if (filter.test(item)) {
|
||||
itemNames.add(item);
|
||||
itemDesc.add(type.getDescription(item));
|
||||
itemTypes.add(getVersionedType(
|
||||
type.getType(item),
|
||||
version
|
||||
));
|
||||
}
|
||||
}
|
||||
return new CompositeType(
|
||||
type.getTypeName(),
|
||||
version != null ? version + " " + type.getDescription() : type.getDescription(),
|
||||
itemNames.toArray(new String[itemNames.size()]),
|
||||
itemDesc.toArray(new String[itemDesc.size()]),
|
||||
itemTypes.toArray(new OpenType<?>[itemTypes.size()])
|
||||
);
|
||||
}
|
||||
|
||||
private OpenType<?> getVersionedType(OpenType<?> type, String version)
|
||||
throws OpenDataException
|
||||
{
|
||||
if (type instanceof ArrayType) {
|
||||
return getVersionedArrayType((ArrayType)type, version);
|
||||
}
|
||||
if (type instanceof CompositeType) {
|
||||
return getVersionedCompositeType((CompositeType)type, version);
|
||||
}
|
||||
if (type instanceof TabularType) {
|
||||
return getVersionedTabularType((TabularType)type, version);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private ArrayType<?> getVersionedArrayType(ArrayType<?> type, String version)
|
||||
throws OpenDataException
|
||||
{
|
||||
if (type.isPrimitiveArray()) {
|
||||
return type;
|
||||
}
|
||||
OpenType<?> ot = getVersionedType(
|
||||
type.getElementOpenType(),
|
||||
version
|
||||
);
|
||||
if (ot instanceof SimpleType) {
|
||||
return new ArrayType<>((SimpleType<?>)ot, type.isPrimitiveArray());
|
||||
} else {
|
||||
return new ArrayType<>(type.getDimension(), ot);
|
||||
}
|
||||
}
|
||||
|
||||
private TabularType getVersionedTabularType(TabularType type, String version)
|
||||
throws OpenDataException
|
||||
{
|
||||
CompositeType ct = getVersionedCompositeType(
|
||||
type.getRowType(),
|
||||
version
|
||||
);
|
||||
|
||||
if (ct != null) {
|
||||
return new TabularType(
|
||||
type.getTypeName(), type.getDescription(), ct,
|
||||
toStringArray(type.getIndexNames()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Predicate<String> getFilter(String type, String version) {
|
||||
Map<String, Predicate<String>> versionMap = filterMap.get(type);
|
||||
if (versionMap == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return versionMap.get(version);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,26 +23,26 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4982289
|
||||
* @bug 4982289 8198253
|
||||
* @summary Test ThreadInfo.from to return a valid
|
||||
* ThreadInfo object. Or throw exception if
|
||||
* the input CompositeData is invalid.
|
||||
* @author Mandy Chung
|
||||
*
|
||||
* @compile OpenTypeConverter.java
|
||||
* @build ThreadInfoCompositeData
|
||||
* @build ThreadInfoCompositeData OpenTypeConverter
|
||||
* @run main ThreadInfoCompositeData
|
||||
*/
|
||||
|
||||
|
||||
import javax.management.openmbean.*;
|
||||
import java.lang.management.LockInfo;
|
||||
import java.lang.management.MonitorInfo;
|
||||
import java.lang.management.ThreadInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ThreadInfoCompositeData {
|
||||
private static StackTraceElement[] ste = new StackTraceElement[1];
|
||||
private static CompositeData[] steCD = new CompositeData[1];
|
||||
private static String lockClassName = "myClass";
|
||||
private static int lockIdentityHashCode = 123456;
|
||||
private static String lockName = lockClassName + '@' +
|
||||
@ -53,55 +53,100 @@ public class ThreadInfoCompositeData {
|
||||
public static void main(String[] argv) throws Exception {
|
||||
// A valid CompositeData is passed to ThreadInfo
|
||||
createGoodCompositeData();
|
||||
// A valid CompositeData for JDK 5.0 ThreadInfo
|
||||
// A valid CompositeData for JDK 5 ThreadInfo
|
||||
// is passed to ThreadInfo
|
||||
createV5ThreadInfo();
|
||||
// ThreadInfo of version N can accept lockedMonitors of version >= N
|
||||
withNewMonitorInfoCompositeData();
|
||||
|
||||
// An invalid CompositeData is passed to ThreadInfo.from()
|
||||
badNameCompositeData();
|
||||
badTypeCompositeData();
|
||||
badMissingCompositeData();
|
||||
withV5StackTraceCompositeData();
|
||||
withInvalidMonitorInfoCompositeData();
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
public static void createGoodCompositeData() throws Exception {
|
||||
CompositeType ct =
|
||||
new CompositeType("MyCompositeType",
|
||||
"CompositeType for ThreadInfo",
|
||||
validItemNames,
|
||||
validItemNames,
|
||||
validItemTypes);
|
||||
CompositeData cd =
|
||||
new CompositeDataSupport(ct,
|
||||
validItemNames,
|
||||
values);
|
||||
CompositeData cd = Factory.makeThreadInfoCompositeData();
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
checkThreadInfo(info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void createV5ThreadInfo() throws Exception {
|
||||
String[] v5ItemNames = new String[NUM_V5_ATTS];
|
||||
OpenType[] v5ItemTypes = new OpenType[NUM_V5_ATTS];
|
||||
Object[] v5ItemValues = new Object[NUM_V5_ATTS];
|
||||
for (int i = 0; i < NUM_V5_ATTS; i++) {
|
||||
v5ItemNames[i] = validItemNames[i];
|
||||
v5ItemTypes[i] = validItemTypes[i];
|
||||
v5ItemValues[i] = values[i];
|
||||
/*
|
||||
* An invalid CompositeData with JDK 9 attributes but missing JDK 6 attributes
|
||||
*/
|
||||
public static void badMissingCompositeData() throws Exception {
|
||||
CompositeData cd = Factory.makeCompositeDataMissingV6();
|
||||
try {
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
throw new RuntimeException("IllegalArgumentException not thrown");
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
|
||||
static final StackTraceElement STE =
|
||||
new StackTraceElement("FooClass", "getFoo", "Foo.java", 100);
|
||||
|
||||
|
||||
/*
|
||||
* Current version of ThreadInfo but an older version of StackTraceElement
|
||||
*/
|
||||
public static void withV5StackTraceCompositeData() throws Exception {
|
||||
CompositeData cd = Factory.makeThreadInfoWithV5StackTrace();
|
||||
try {
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
throw new RuntimeException("IllegalArgumentException not thrown");
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
|
||||
/*
|
||||
* Current version of ThreadInfo but an older version of MonitorInfo
|
||||
* and the value of "lockedStackFrame" attribute is null.
|
||||
*/
|
||||
public static void withInvalidMonitorInfoCompositeData() throws Exception {
|
||||
CompositeData cd = Factory.makeThreadInfoWithIncompatibleMonitorInfo();
|
||||
|
||||
// verify MonitorInfo is valid
|
||||
CompositeData[] monitors = (CompositeData[])cd.get("lockedMonitors");
|
||||
CompositeData ste = (CompositeData)monitors[0].get("lockedStackFrame");
|
||||
if (((Integer)monitors[0].get("lockedStackDepth")) >= 0 || ste != null) {
|
||||
throw new RuntimeException("Expected negative stack depth and null stack frame");
|
||||
}
|
||||
CompositeType ct =
|
||||
new CompositeType("MyCompositeType",
|
||||
"CompositeType for JDK 5.0 ThreadInfo",
|
||||
v5ItemNames,
|
||||
v5ItemNames,
|
||||
v5ItemTypes);
|
||||
CompositeData cd =
|
||||
new CompositeDataSupport(ct,
|
||||
v5ItemNames,
|
||||
v5ItemValues);
|
||||
MonitorInfo minfo = MonitorInfo.from(monitors[0]);
|
||||
checkLockInfo(minfo);
|
||||
if (minfo.getLockedStackFrame() != null) {
|
||||
throw new RuntimeException("Expected null stack frame");
|
||||
}
|
||||
|
||||
try {
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
throw new RuntimeException("IllegalArgumentException not thrown");
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
|
||||
/*
|
||||
* ThreadInfo of version N can accept lockedMonitors of version >= N
|
||||
*/
|
||||
public static void withNewMonitorInfoCompositeData() throws Exception {
|
||||
CompositeData cd = Factory.makeThreadInfoWithNewMonitorInfo();
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
checkThreadInfo(info);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test CompositeData representing JDK 5 ThreadInfo
|
||||
*/
|
||||
public static void createV5ThreadInfo() throws Exception {
|
||||
CompositeData cd = Factory.makeThreadInfoV5CompositeData();
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
checkThreadInfoV5(info);
|
||||
}
|
||||
|
||||
static void checkThreadInfo(ThreadInfo info) throws Exception {
|
||||
if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) {
|
||||
static void checkThreadInfoV5(ThreadInfo info) {
|
||||
Object[] values = Factory.VALUES;
|
||||
|
||||
if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) {
|
||||
throw new RuntimeException("Thread Id = " + info.getThreadId() +
|
||||
" expected = " + values[THREAD_ID]);
|
||||
}
|
||||
@ -148,30 +193,35 @@ public class ThreadInfoCompositeData {
|
||||
info.getLockOwnerName() + " expected = " +
|
||||
values[LOCK_OWNER_NAME]);
|
||||
}
|
||||
if (!values[DAEMON].equals(info.isDaemon())) {
|
||||
throw new RuntimeException("Daemon = " +
|
||||
info.isDaemon() + " expected = " +
|
||||
values[DAEMON]);
|
||||
}
|
||||
|
||||
checkStackTrace(info.getStackTrace());
|
||||
|
||||
checkLockInfo(info.getLockInfo());
|
||||
}
|
||||
|
||||
static void checkThreadInfo(ThreadInfo info) {
|
||||
Object[] values = Factory.VALUES;
|
||||
|
||||
checkThreadInfoV5(info);
|
||||
|
||||
if (!values[DAEMON].equals(info.isDaemon())) {
|
||||
throw new RuntimeException("Daemon = " +
|
||||
info.isDaemon() + " expected = " + values[DAEMON]);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkStackTrace(StackTraceElement[] s)
|
||||
throws Exception {
|
||||
if (ste.length != s.length) {
|
||||
private static void checkStackTrace(StackTraceElement[] s) {
|
||||
if (s.length != 1) {
|
||||
throw new RuntimeException("Stack Trace length = " +
|
||||
s.length + " expected = " + ste.length);
|
||||
s.length + " expected = 1");
|
||||
}
|
||||
|
||||
StackTraceElement s1 = ste[0];
|
||||
StackTraceElement s1 = STE;
|
||||
StackTraceElement s2 = s[0];
|
||||
|
||||
if (!s1.getClassName().equals(s2.getClassName())) {
|
||||
throw new RuntimeException("Class name = " +
|
||||
s2.getClassName() + " expected = " + s1.getClassName());
|
||||
// these attributes may be null
|
||||
if (!Objects.equals(s1.getClassLoaderName(), s2.getClassLoaderName())) {
|
||||
throw new RuntimeException("Class loader name = " +
|
||||
s2.getClassLoaderName() + " expected = " + s1.getClassLoaderName());
|
||||
}
|
||||
if (!Objects.equals(s1.getModuleName(), s2.getModuleName())) {
|
||||
throw new RuntimeException("Module name = " +
|
||||
@ -181,6 +231,11 @@ public class ThreadInfoCompositeData {
|
||||
throw new RuntimeException("Module version = " +
|
||||
s2.getModuleVersion() + " expected = " + s1.getModuleVersion());
|
||||
}
|
||||
|
||||
if (!s1.getClassName().equals(s2.getClassName())) {
|
||||
throw new RuntimeException("Class name = " +
|
||||
s2.getClassName() + " expected = " + s1.getClassName());
|
||||
}
|
||||
if (!s1.getMethodName().equals(s2.getMethodName())) {
|
||||
throw new RuntimeException("Method name = " +
|
||||
s2.getMethodName() + " expected = " + s1.getMethodName());
|
||||
@ -195,8 +250,7 @@ public class ThreadInfoCompositeData {
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkLockInfo(LockInfo li)
|
||||
throws Exception {
|
||||
private static void checkLockInfo(LockInfo li) {
|
||||
if (!li.getClassName().equals(lockInfo.getClassName())) {
|
||||
throw new RuntimeException("Class Name = " +
|
||||
li.getClassName() + " expected = " + lockInfo.getClassName());
|
||||
@ -209,227 +263,493 @@ public class ThreadInfoCompositeData {
|
||||
}
|
||||
|
||||
public static void badNameCompositeData() throws Exception {
|
||||
CompositeType ct =
|
||||
new CompositeType("MyCompositeType",
|
||||
"CompositeType for ThreadInfo",
|
||||
badItemNames,
|
||||
badItemNames,
|
||||
validItemTypes);
|
||||
CompositeData cd =
|
||||
new CompositeDataSupport(ct,
|
||||
badItemNames,
|
||||
values);
|
||||
|
||||
CompositeData cd = Factory.makeCompositeDataWithBadNames();
|
||||
try {
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Expected exception: " +
|
||||
e.getMessage());
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException(
|
||||
"IllegalArgumentException not thrown");
|
||||
throw new RuntimeException("IllegalArgumentException not thrown");
|
||||
} catch (IllegalArgumentException e) { }
|
||||
}
|
||||
|
||||
public static void badTypeCompositeData() throws Exception {
|
||||
CompositeType ct =
|
||||
new CompositeType("MyCompositeType",
|
||||
"CompositeType for ThreadInfo",
|
||||
validItemNames,
|
||||
validItemNames,
|
||||
badItemTypes);
|
||||
|
||||
// patch values[STACK_TRACE] to Long
|
||||
values[STACK_TRACE] = new Long(1000);
|
||||
values[LOCK_INFO] = new Long(1000);
|
||||
CompositeData cd =
|
||||
new CompositeDataSupport(ct,
|
||||
validItemNames,
|
||||
values);
|
||||
CompositeData cd = Factory.makeCompositeDataWithBadTypes();
|
||||
|
||||
try {
|
||||
ThreadInfo info = ThreadInfo.from(cd);
|
||||
} catch (IllegalArgumentException e) {
|
||||
System.out.println("Expected exception: " +
|
||||
e.getMessage());
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException(
|
||||
"IllegalArgumentException not thrown");
|
||||
throw new RuntimeException("IllegalArgumentException not thrown");
|
||||
} catch (IllegalArgumentException e) { }
|
||||
}
|
||||
|
||||
private static final int THREAD_ID = 0;
|
||||
private static final int THREAD_NAME = 1;
|
||||
private static final int THREAD_STATE = 2;
|
||||
private static final int BLOCKED_TIME = 3;
|
||||
private static final int BLOCKED_COUNT = 4;
|
||||
private static final int WAITED_TIME = 5;
|
||||
private static final int WAITED_COUNT = 6;
|
||||
private static final int LOCK_NAME = 7;
|
||||
private static final int LOCK_OWNER_ID = 8;
|
||||
private static final int THREAD_ID = 0;
|
||||
private static final int THREAD_NAME = 1;
|
||||
private static final int THREAD_STATE = 2;
|
||||
private static final int BLOCKED_TIME = 3;
|
||||
private static final int BLOCKED_COUNT = 4;
|
||||
private static final int WAITED_TIME = 5;
|
||||
private static final int WAITED_COUNT = 6;
|
||||
private static final int LOCK_NAME = 7;
|
||||
private static final int LOCK_OWNER_ID = 8;
|
||||
private static final int LOCK_OWNER_NAME = 9;
|
||||
private static final int STACK_TRACE = 10;
|
||||
private static final int SUSPENDED = 11;
|
||||
private static final int IN_NATIVE = 12;
|
||||
private static final int NUM_V5_ATTS = 13;
|
||||
// JDK 6.0 ThreadInfo attributes
|
||||
private static final int LOCK_INFO = 13;
|
||||
// JDK 9.0 ThreadInfo attributes
|
||||
private static final int DAEMON = 14;
|
||||
private static final int PRIORITY = 15;
|
||||
private static final int STACK_TRACE = 10;
|
||||
private static final int SUSPENDED = 11;
|
||||
private static final int IN_NATIVE = 12;
|
||||
// JDK 6 ThreadInfo attributes
|
||||
private static final int LOCK_INFO = 13;
|
||||
private static final int LOCKED_MONITORS = 14;
|
||||
private static final int LOCKED_SYNCS = 15;
|
||||
// JDK 9 ThreadInfo attributes
|
||||
private static final int DAEMON = 16;
|
||||
private static final int PRIORITY = 17;
|
||||
|
||||
private static final String[] validItemNames = {
|
||||
"threadId",
|
||||
"threadName",
|
||||
"threadState",
|
||||
"blockedTime",
|
||||
"blockedCount",
|
||||
"waitedTime",
|
||||
"waitedCount",
|
||||
"lockName",
|
||||
"lockOwnerId",
|
||||
"lockOwnerName",
|
||||
"stackTrace",
|
||||
"suspended",
|
||||
"inNative",
|
||||
"lockInfo",
|
||||
"daemon",
|
||||
"priority",
|
||||
};
|
||||
static class Factory {
|
||||
|
||||
private static OpenType[] validItemTypes = {
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
null, // ArrayType for StackTraceElement[]
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.BOOLEAN,
|
||||
null, // CompositeType for LockInfo
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.INTEGER,
|
||||
};
|
||||
static final CompositeType STE_COMPOSITE_TYPE;
|
||||
static final CompositeType LOCK_INFO_COMPOSITE_TYPE;
|
||||
static final CompositeType MONITOR_INFO_COMPOSITE_TYPE;
|
||||
static final ArrayType STE_ARRAY_COMPOSITE_TYPE;
|
||||
static final ArrayType LOCK_INFO_ARRAY_COMPOSITE_TYPE;
|
||||
static final ArrayType MONITOR_INFO_ARRAY_COMPOSITE_TYPE;
|
||||
|
||||
private static Object[] values = {
|
||||
new Long(100),
|
||||
"FooThread",
|
||||
"RUNNABLE",
|
||||
new Long(200),
|
||||
new Long(10),
|
||||
new Long(300),
|
||||
new Long(20),
|
||||
lockName,
|
||||
new Long(99),
|
||||
"BarThread",
|
||||
steCD,
|
||||
new Boolean(false),
|
||||
new Boolean(false),
|
||||
null, // To be initialized to lockInfoCD
|
||||
new Boolean(false),
|
||||
Thread.NORM_PRIORITY,
|
||||
};
|
||||
static {
|
||||
CompositeType steCType = null;
|
||||
CompositeType lockInfoCType = null;
|
||||
CompositeType monitorInfoCType = null;
|
||||
ArrayType steArrayType = null;
|
||||
ArrayType lockInfoArrayType = null;
|
||||
ArrayType monitorInfoArrayType = null;
|
||||
|
||||
private static final String[] steItemNames = {
|
||||
"classLoaderName",
|
||||
"moduleName",
|
||||
"moduleVersion",
|
||||
"className",
|
||||
"methodName",
|
||||
"fileName",
|
||||
"lineNumber",
|
||||
"nativeMethod",
|
||||
};
|
||||
try {
|
||||
steCType = (CompositeType) OpenTypeConverter.toOpenType(StackTraceElement.class);
|
||||
lockInfoCType = (CompositeType) OpenTypeConverter.toOpenType(LockInfo.class);
|
||||
monitorInfoCType = (CompositeType) OpenTypeConverter.toOpenType(MonitorInfo.class);
|
||||
steArrayType = new ArrayType(1, steCType);
|
||||
lockInfoArrayType = new ArrayType(1, lockInfoCType);
|
||||
monitorInfoArrayType = new ArrayType(1, monitorInfoCType);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
STE_COMPOSITE_TYPE = steCType;
|
||||
LOCK_INFO_COMPOSITE_TYPE = lockInfoCType;
|
||||
MONITOR_INFO_COMPOSITE_TYPE = monitorInfoCType;
|
||||
STE_ARRAY_COMPOSITE_TYPE = steArrayType;
|
||||
LOCK_INFO_ARRAY_COMPOSITE_TYPE = lockInfoArrayType;
|
||||
MONITOR_INFO_ARRAY_COMPOSITE_TYPE = monitorInfoArrayType;
|
||||
}
|
||||
|
||||
private static final String[] lockInfoItemNames = {
|
||||
"className",
|
||||
"identityHashCode",
|
||||
};
|
||||
static CompositeData makeThreadInfoCompositeData() throws OpenDataException {
|
||||
CompositeType ct = new CompositeType("MyCompositeType",
|
||||
"CompositeType for ThreadInfo",
|
||||
ITEM_NAMES,
|
||||
ITEM_NAMES,
|
||||
ITEM_TYPES);
|
||||
return new CompositeDataSupport(ct, ITEM_NAMES, VALUES);
|
||||
}
|
||||
|
||||
static {
|
||||
// create stack trace element
|
||||
ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100);
|
||||
static CompositeData makeThreadInfoV5CompositeData() throws OpenDataException {
|
||||
CompositeType ct = new CompositeType("MyCompositeType",
|
||||
"CompositeType for JDK 5 ThreadInfo",
|
||||
V5_ITEM_NAMES,
|
||||
V5_ITEM_NAMES,
|
||||
V5_ITEM_TYPES);
|
||||
return new CompositeDataSupport(ct, V5_ITEM_NAMES, V5_VALUES);
|
||||
}
|
||||
|
||||
// initialize the ste[0] and values and validItemTypes
|
||||
try {
|
||||
CompositeType steCType = (CompositeType)
|
||||
OpenTypeConverter.toOpenType(StackTraceElement.class);
|
||||
validItemTypes[STACK_TRACE] = new ArrayType(1, steCType);
|
||||
|
||||
final Object[] steValue = {
|
||||
ste[0].getClassLoaderName(),
|
||||
ste[0].getModuleName(),
|
||||
ste[0].getModuleVersion(),
|
||||
ste[0].getClassName(),
|
||||
ste[0].getMethodName(),
|
||||
ste[0].getFileName(),
|
||||
new Integer(ste[0].getLineNumber()),
|
||||
new Boolean(ste[0].isNativeMethod()),
|
||||
static CompositeData makeCompositeDataWithBadTypes() throws OpenDataException {
|
||||
OpenType[] badItemTypes = {
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG, // bad type
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.LONG, // bad type
|
||||
SimpleType.LONG, // bad type
|
||||
SimpleType.LONG, // bad type
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.INTEGER,
|
||||
};
|
||||
|
||||
steCD[0] =
|
||||
new CompositeDataSupport(steCType,
|
||||
steItemNames,
|
||||
steValue);
|
||||
CompositeType ct =
|
||||
new CompositeType("Bad item types",
|
||||
"CompositeType for ThreadInfo",
|
||||
ITEM_NAMES,
|
||||
ITEM_NAMES,
|
||||
badItemTypes);
|
||||
|
||||
CompositeType lockInfoCType = (CompositeType)
|
||||
OpenTypeConverter.toOpenType(LockInfo.class);
|
||||
validItemTypes[LOCK_INFO] = lockInfoCType;
|
||||
// Copy before mutating to avoid affecting other tests.
|
||||
Object[] localValues = VALUES.clone();
|
||||
|
||||
final Object[] lockInfoValue = {
|
||||
// patch values[STACK_TRACE] to Long
|
||||
localValues[STACK_TRACE] = Long.valueOf(1000);
|
||||
localValues[LOCK_INFO] = Long.valueOf(1000);
|
||||
localValues[LOCKED_MONITORS] = Long.valueOf(1000);
|
||||
localValues[LOCKED_SYNCS] = Long.valueOf(1000);
|
||||
return new CompositeDataSupport(ct, ITEM_NAMES, localValues);
|
||||
}
|
||||
|
||||
static CompositeData makeCompositeDataWithBadNames() throws OpenDataException {
|
||||
String[] badItemNames = ITEM_NAMES.clone();
|
||||
badItemNames[STACK_TRACE] = "BadStackTrace"; // bad item name
|
||||
|
||||
CompositeType ct = new CompositeType("Bad item names",
|
||||
"CompositeType for ThreadInfo",
|
||||
badItemNames,
|
||||
badItemNames,
|
||||
ITEM_TYPES);
|
||||
return new CompositeDataSupport(ct,
|
||||
badItemNames,
|
||||
VALUES);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CompositeData of ThreadInfo without JDK 6 attributes
|
||||
*/
|
||||
static CompositeData makeCompositeDataMissingV6() throws OpenDataException {
|
||||
String[] itemNames = concat(V5_ITEM_NAMES, V9_ITEM_NAMES).toArray(String[]::new);
|
||||
OpenType[] itemTypes = concat(V5_ITEM_TYPES, V9_ITEM_TYPES).toArray(OpenType[]::new);
|
||||
Object[] values = concat(V5_VALUES, V9_VALUES).toArray(Object[]::new);
|
||||
|
||||
CompositeType ct =
|
||||
new CompositeType("InvalidCompositeType",
|
||||
"CompositeType for ThreadInfo",
|
||||
itemNames,
|
||||
itemNames,
|
||||
itemTypes);
|
||||
return new CompositeDataSupport(ct, itemNames, values);
|
||||
}
|
||||
|
||||
static CompositeData makeStackTraceElement() {
|
||||
Object[] steValue = {
|
||||
STE.getClassLoaderName(),
|
||||
STE.getModuleName(),
|
||||
STE.getModuleVersion(),
|
||||
STE.getClassName(),
|
||||
STE.getMethodName(),
|
||||
STE.getFileName(),
|
||||
Integer.valueOf(STE.getLineNumber()),
|
||||
Boolean.valueOf(STE.isNativeMethod()),
|
||||
};
|
||||
|
||||
try {
|
||||
return new CompositeDataSupport(STE_COMPOSITE_TYPE,
|
||||
STE_ITEM_NAMES,
|
||||
steValue);
|
||||
} catch (OpenDataException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static CompositeData makeStackTraceElementV5() throws OpenDataException {
|
||||
CompositeType steV5CType =
|
||||
new CompositeType("JDK 5 StackTraceElement",
|
||||
"CompositeType for JDK 5 StackTraceElement",
|
||||
STE_V5_ITEM_NAMES,
|
||||
STE_V5_ITEM_NAMES,
|
||||
STE_V5_ITEM_TYPES);
|
||||
|
||||
Object[] steV5Value = {
|
||||
STE.getClassName(),
|
||||
STE.getMethodName(),
|
||||
STE.getFileName(),
|
||||
Integer.valueOf(STE.getLineNumber()),
|
||||
Boolean.valueOf(STE.isNativeMethod()),
|
||||
};
|
||||
|
||||
return new CompositeDataSupport(steV5CType, STE_V5_ITEM_NAMES, steV5Value);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CompositeData of ThreadInfo without JDK 5 StackTraceElement
|
||||
*/
|
||||
static CompositeData makeThreadInfoWithV5StackTrace() throws OpenDataException {
|
||||
OpenType[] badTypes = ITEM_TYPES.clone();
|
||||
Object[] badValues = VALUES.clone();
|
||||
|
||||
CompositeData[] stackTrace = new CompositeData[1];
|
||||
stackTrace[0] = makeStackTraceElementV5();
|
||||
badTypes[STACK_TRACE] = new ArrayType(1, stackTrace[0].getCompositeType());
|
||||
badValues[STACK_TRACE] = stackTrace;
|
||||
CompositeType ct = new CompositeType("CompositeType",
|
||||
"ThreadInfo with JDK 5 StackTraceElement",
|
||||
ITEM_NAMES,
|
||||
ITEM_NAMES,
|
||||
badTypes);
|
||||
return new CompositeDataSupport(ct, ITEM_NAMES, badValues);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create MonitorInfo with JDK 5 StackTraceElement (i.e. JDK 6 MonitorInfo)
|
||||
* The value of "lockedStackFrame" attribute is null to ensure that
|
||||
* the validation is done.
|
||||
*/
|
||||
static CompositeData makeV6MonitorInfo() throws OpenDataException {
|
||||
CompositeData steV5 = makeStackTraceElementV5();
|
||||
|
||||
String[] names = MONITOR_INFO_COMPOSITE_TYPE.keySet().toArray(new String[0]);
|
||||
OpenType[] types = new OpenType[names.length];
|
||||
for (int i=0; i < names.length; i++) {
|
||||
String n = names[i];
|
||||
types[i] = "lockedStackFrame".equals(n)
|
||||
? steV5.getCompositeType()
|
||||
: MONITOR_INFO_COMPOSITE_TYPE.getType(n);
|
||||
}
|
||||
|
||||
CompositeType ctype =
|
||||
new CompositeType("JDK 6 MonitorInfo",
|
||||
"CompositeType for JDK 6 MonitorInfo",
|
||||
names,
|
||||
names,
|
||||
types);
|
||||
|
||||
Object[] values = {
|
||||
lockClassName,
|
||||
lockIdentityHashCode,
|
||||
-1,
|
||||
null
|
||||
};
|
||||
|
||||
return new CompositeDataSupport(ctype, names, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CompositeData of ThreadInfo with incompatible MonitorInfo
|
||||
*/
|
||||
static CompositeData makeThreadInfoWithIncompatibleMonitorInfo() throws OpenDataException {
|
||||
OpenType[] badTypes = ITEM_TYPES.clone();
|
||||
Object[] badValues = VALUES.clone();
|
||||
|
||||
CompositeData[] lockedMonitors = new CompositeData[1];
|
||||
lockedMonitors[0] = makeV6MonitorInfo();
|
||||
badTypes[LOCKED_MONITORS] = new ArrayType(1, lockedMonitors[0].getCompositeType());
|
||||
badValues[LOCKED_MONITORS] = lockedMonitors;
|
||||
CompositeType ct = new CompositeType("CompositeType",
|
||||
"ThreadInfo with incompatible MonitorInfo",
|
||||
ITEM_NAMES,
|
||||
ITEM_NAMES,
|
||||
badTypes);
|
||||
return new CompositeDataSupport(ct, ITEM_NAMES, badValues);
|
||||
}
|
||||
|
||||
static CompositeData makeNewMonitorInfo() throws OpenDataException {
|
||||
String[] names = Stream.concat(MONITOR_INFO_COMPOSITE_TYPE.keySet().stream(),
|
||||
Stream.of("extra")).toArray(String[]::new);
|
||||
OpenType[] types = new OpenType[names.length];
|
||||
for (int i=0; i < names.length; i++) {
|
||||
String n = names[i];
|
||||
types[i] = "extra".equals(n)
|
||||
? SimpleType.STRING
|
||||
: MONITOR_INFO_COMPOSITE_TYPE.getType(n);
|
||||
}
|
||||
|
||||
CompositeType compositeType =
|
||||
new CompositeType("JDK X MonitorInfo",
|
||||
"CompositeType for JDK X MonitorInfo",
|
||||
names,
|
||||
names,
|
||||
types);
|
||||
|
||||
Object[] values = {
|
||||
lockClassName,
|
||||
lockIdentityHashCode,
|
||||
Integer.valueOf(1),
|
||||
makeStackTraceElement(),
|
||||
"extra"
|
||||
};
|
||||
|
||||
return new CompositeDataSupport(compositeType, names, values);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a CompositeData of ThreadInfo with a newer version of MonitorInfo
|
||||
*/
|
||||
static CompositeData makeThreadInfoWithNewMonitorInfo() throws OpenDataException {
|
||||
OpenType[] types = ITEM_TYPES.clone();
|
||||
Object[] badValues = VALUES.clone();
|
||||
|
||||
CompositeData[] lockedMonitors = new CompositeData[1];
|
||||
lockedMonitors[0] = makeNewMonitorInfo();
|
||||
types[LOCKED_MONITORS] = new ArrayType(1, lockedMonitors[0].getCompositeType());
|
||||
badValues[LOCKED_MONITORS] = lockedMonitors;
|
||||
CompositeType ct = new CompositeType("CompositeType",
|
||||
"ThreadInfo with JDK 5 MonitorInfo",
|
||||
ITEM_NAMES,
|
||||
ITEM_NAMES,
|
||||
types);
|
||||
return new CompositeDataSupport(ct, ITEM_NAMES, badValues);
|
||||
}
|
||||
|
||||
static CompositeData makeLockInfo() {
|
||||
Object[] lockInfoValue = {
|
||||
lockInfo.getClassName(),
|
||||
lockInfo.getIdentityHashCode(),
|
||||
};
|
||||
|
||||
values[LOCK_INFO] =
|
||||
new CompositeDataSupport(lockInfoCType,
|
||||
lockInfoItemNames,
|
||||
lockInfoValue);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
try {
|
||||
return new CompositeDataSupport(LOCK_INFO_COMPOSITE_TYPE,
|
||||
LOCK_INFO_ITEM_NAMES,
|
||||
lockInfoValue);
|
||||
} catch (OpenDataException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
static CompositeData[] makeLockedSynchronizers() {
|
||||
CompositeData[] lockedSyncs = new CompositeData[1];
|
||||
lockedSyncs[0] = makeLockInfo();
|
||||
return lockedSyncs;
|
||||
}
|
||||
|
||||
static CompositeData[] makeLockedMonitors() {
|
||||
CompositeData[] lockedMonitorsCD = new CompositeData[1];
|
||||
|
||||
Object[] lockedMonitorsValue = {
|
||||
lockInfo.getClassName(),
|
||||
lockInfo.getIdentityHashCode(),
|
||||
makeStackTraceElement(),
|
||||
Integer.valueOf(1),
|
||||
};
|
||||
try {
|
||||
lockedMonitorsCD[0] =
|
||||
new CompositeDataSupport(MONITOR_INFO_COMPOSITE_TYPE,
|
||||
LOCKED_MONITORS_ITEM_NAMES,
|
||||
lockedMonitorsValue);
|
||||
} catch (OpenDataException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return lockedMonitorsCD;
|
||||
}
|
||||
|
||||
static final String[] V5_ITEM_NAMES = {
|
||||
"threadId",
|
||||
"threadName",
|
||||
"threadState",
|
||||
"blockedTime",
|
||||
"blockedCount",
|
||||
"waitedTime",
|
||||
"waitedCount",
|
||||
"lockName",
|
||||
"lockOwnerId",
|
||||
"lockOwnerName",
|
||||
"stackTrace",
|
||||
"suspended",
|
||||
"inNative",
|
||||
};
|
||||
|
||||
static final String[] V6_ITEM_NAMES = {
|
||||
"lockInfo",
|
||||
"lockedMonitors",
|
||||
"lockedSynchronizers",
|
||||
};
|
||||
|
||||
static final String[] V9_ITEM_NAMES = {
|
||||
"daemon",
|
||||
"priority",
|
||||
};
|
||||
|
||||
static final OpenType[] V5_ITEM_TYPES = {
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
STE_ARRAY_COMPOSITE_TYPE,
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.BOOLEAN,
|
||||
};
|
||||
|
||||
static final OpenType[] V6_ITEM_TYPES = {
|
||||
LOCK_INFO_COMPOSITE_TYPE,
|
||||
MONITOR_INFO_ARRAY_COMPOSITE_TYPE,
|
||||
LOCK_INFO_ARRAY_COMPOSITE_TYPE,
|
||||
};
|
||||
|
||||
static final OpenType[] V9_ITEM_TYPES = {
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.INTEGER,
|
||||
};
|
||||
|
||||
static final String[] STE_ITEM_NAMES = {
|
||||
"classLoaderName",
|
||||
"moduleName",
|
||||
"moduleVersion",
|
||||
"className",
|
||||
"methodName",
|
||||
"fileName",
|
||||
"lineNumber",
|
||||
"nativeMethod",
|
||||
};
|
||||
|
||||
static final String[] STE_V5_ITEM_NAMES = Arrays.copyOfRange(STE_ITEM_NAMES, 3, 8);
|
||||
|
||||
static final OpenType[] STE_V5_ITEM_TYPES = {
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.INTEGER,
|
||||
SimpleType.BOOLEAN
|
||||
};
|
||||
|
||||
static final String[] LOCK_INFO_ITEM_NAMES = {
|
||||
"className",
|
||||
"identityHashCode",
|
||||
};
|
||||
|
||||
static final String[] LOCKED_MONITORS_ITEM_NAMES = {
|
||||
LOCK_INFO_ITEM_NAMES[0],
|
||||
LOCK_INFO_ITEM_NAMES[1],
|
||||
"lockedStackFrame",
|
||||
"lockedStackDepth",
|
||||
};
|
||||
|
||||
static final Object[] V5_VALUES = {
|
||||
Long.valueOf(100),
|
||||
"FooThread",
|
||||
"RUNNABLE",
|
||||
Long.valueOf(200),
|
||||
Long.valueOf(10),
|
||||
Long.valueOf(300),
|
||||
Long.valueOf(20),
|
||||
lockName,
|
||||
Long.valueOf(99),
|
||||
"BarThread",
|
||||
new CompositeData[] { makeStackTraceElement() },
|
||||
Boolean.valueOf(false),
|
||||
Boolean.valueOf(false),
|
||||
};
|
||||
|
||||
static final Object[] V6_VALUES = {
|
||||
makeLockInfo(),
|
||||
makeLockedMonitors(),
|
||||
makeLockedSynchronizers(),
|
||||
};
|
||||
|
||||
static final Object[] V9_VALUES = {
|
||||
Boolean.valueOf(true),
|
||||
Thread.NORM_PRIORITY,
|
||||
};
|
||||
|
||||
static final String[] ITEM_NAMES =
|
||||
concat(V5_ITEM_NAMES, V6_ITEM_NAMES, V9_ITEM_NAMES).toArray(String[]::new);
|
||||
|
||||
static final OpenType[] ITEM_TYPES =
|
||||
concat(V5_ITEM_TYPES, V6_ITEM_TYPES, V9_ITEM_TYPES).toArray(OpenType[]::new);
|
||||
|
||||
static final Object[] VALUES =
|
||||
concat(V5_VALUES, V6_VALUES, V9_VALUES).toArray(Object[]::new);
|
||||
|
||||
static <T> Stream<T> concat(T[]... streams) {
|
||||
return Stream.of(streams).flatMap(a -> Arrays.stream(a));
|
||||
}
|
||||
}
|
||||
|
||||
private static final String[] badItemNames = {
|
||||
"threadId",
|
||||
"threadName",
|
||||
"threadState",
|
||||
"blockedTime",
|
||||
"blockedCount",
|
||||
"waitedTime",
|
||||
"waitedCount",
|
||||
"lockName",
|
||||
"lockOwnerId",
|
||||
"lockOwnerName",
|
||||
"BadStackTrace", // bad item name
|
||||
"suspended",
|
||||
"inNative",
|
||||
"lockInfo",
|
||||
"daemon",
|
||||
"priority",
|
||||
};
|
||||
private static final OpenType[] badItemTypes = {
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG,
|
||||
SimpleType.STRING,
|
||||
SimpleType.LONG, // bad type
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.LONG, // bad type
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.INTEGER,
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@ -6,6 +28,7 @@ import javax.management.openmbean.CompositeDataSupport;
|
||||
import javax.management.openmbean.CompositeType;
|
||||
import javax.management.openmbean.OpenType;
|
||||
import javax.management.openmbean.SimpleType;
|
||||
|
||||
import sun.management.StackTraceElementCompositeData;
|
||||
|
||||
import org.testng.annotations.*;
|
||||
@ -14,6 +37,7 @@ import static org.testng.Assert.*;
|
||||
/*
|
||||
* @test
|
||||
* @bug 8139587
|
||||
* @modules java.management/sun.management
|
||||
* @summary Check backward compatibility of StackTraceElementCompositeData
|
||||
* @author Jaroslav Bachorik
|
||||
*
|
||||
@ -22,21 +46,33 @@ import static org.testng.Assert.*;
|
||||
|
||||
public class CompatibilityTest {
|
||||
private static CompositeType compositeTypeV6;
|
||||
private static Map<String, Object> itemsV6;
|
||||
private static CompositeData compositeDataV6;
|
||||
private static CompositeType compositeType;
|
||||
|
||||
// Attribute names
|
||||
private static final String CLASS_LOADER_NAME = "classLoaderName";
|
||||
private static final String MODULE_NAME = "moduleName";
|
||||
private static final String MODULE_VERSION = "moduleVersion";
|
||||
private static final String CLASS_NAME = "className";
|
||||
private static final String METHOD_NAME = "methodName";
|
||||
private static final String FILE_NAME = "fileName";
|
||||
private static final String LINE_NUMBER = "lineNumber";
|
||||
private static final String NATIVE_METHOD = "nativeMethod";
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws Exception {
|
||||
String[] v6Names = {
|
||||
CLASS_NAME, METHOD_NAME, FILE_NAME, NATIVE_METHOD, LINE_NUMBER
|
||||
};
|
||||
String[] names = {
|
||||
CLASS_LOADER_NAME, MODULE_NAME, MODULE_VERSION,
|
||||
CLASS_NAME, METHOD_NAME, FILE_NAME, NATIVE_METHOD, LINE_NUMBER
|
||||
};
|
||||
compositeTypeV6 = new CompositeType(
|
||||
StackTraceElement.class.getName(),
|
||||
"StackTraceElement",
|
||||
new String[]{
|
||||
"className", "methodName", "fileName", "nativeMethod", "lineNumber"
|
||||
},
|
||||
new String[]{
|
||||
"className", "methodName", "fileName", "nativeMethod", "lineNumber"
|
||||
},
|
||||
new OpenType[]{
|
||||
v6Names,
|
||||
v6Names,
|
||||
new OpenType[] {
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
@ -44,20 +80,52 @@ public class CompatibilityTest {
|
||||
SimpleType.INTEGER
|
||||
}
|
||||
);
|
||||
compositeType = new CompositeType(
|
||||
StackTraceElement.class.getName(),
|
||||
"StackTraceElement",
|
||||
names,
|
||||
names,
|
||||
new OpenType[] {
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.STRING,
|
||||
SimpleType.BOOLEAN,
|
||||
SimpleType.INTEGER
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
itemsV6 = new HashMap<>();
|
||||
itemsV6.put("className", "MyClass");
|
||||
itemsV6.put("methodName", "myMethod");
|
||||
itemsV6.put("fileName", "MyClass.java");
|
||||
itemsV6.put("nativeMethod", false);
|
||||
itemsV6.put("lineNumber", 123);
|
||||
private static CompositeData makeCompositeDataV6() throws Exception {
|
||||
Map<String, Object> itemsV6 = new HashMap<>();
|
||||
itemsV6.put(CLASS_NAME, "MyClass");
|
||||
itemsV6.put(METHOD_NAME, "myMethod");
|
||||
itemsV6.put(FILE_NAME, "MyClass.java");
|
||||
itemsV6.put(NATIVE_METHOD, false);
|
||||
itemsV6.put(LINE_NUMBER, 123);
|
||||
|
||||
compositeDataV6 = new CompositeDataSupport(compositeTypeV6, itemsV6);
|
||||
return new CompositeDataSupport(compositeTypeV6, itemsV6);
|
||||
}
|
||||
|
||||
private static CompositeData makeCompositeData() throws Exception {
|
||||
Map<String, Object> items = new HashMap<>();
|
||||
items.put(CLASS_LOADER_NAME, "app");
|
||||
items.put(MODULE_NAME, "m");
|
||||
items.put(MODULE_VERSION, "1.0");
|
||||
items.put(CLASS_NAME, "MyClass");
|
||||
items.put(METHOD_NAME, "myMethod");
|
||||
items.put(FILE_NAME, "MyClass.java");
|
||||
items.put(NATIVE_METHOD, false);
|
||||
items.put(LINE_NUMBER, 123);
|
||||
|
||||
return new CompositeDataSupport(compositeType, items);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testV6Compatibility() throws Exception {
|
||||
StackTraceElement ste = StackTraceElementCompositeData.from(compositeDataV6);
|
||||
StackTraceElement ste = StackTraceElementCompositeData.from(makeCompositeDataV6());
|
||||
|
||||
assertNotNull(ste);
|
||||
assertEquals(ste.getClassName(), "MyClass");
|
||||
@ -69,5 +137,22 @@ public class CompatibilityTest {
|
||||
assertNull(ste.getModuleName());
|
||||
assertNull(ste.getModuleVersion());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
StackTraceElement ste = StackTraceElementCompositeData.from(makeCompositeData());
|
||||
|
||||
assertNotNull(ste);
|
||||
|
||||
assertEquals(ste.getModuleName(), "m");
|
||||
assertEquals(ste.getModuleVersion(), "1.0");
|
||||
assertEquals(ste.getClassLoaderName(), "app");
|
||||
|
||||
assertEquals(ste.getClassName(), "MyClass");
|
||||
assertEquals(ste.getMethodName(), "myMethod");
|
||||
assertEquals(ste.getFileName(), "MyClass.java");
|
||||
assertEquals(ste.isNativeMethod(), false);
|
||||
assertEquals(ste.getLineNumber(), 123);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user