--- a/src/java.management/share/classes/java/lang/management/MonitorInfo.java Thu Mar 01 11:02:40 2018 +0100
+++ b/src/java.management/share/classes/java/lang/management/MonitorInfo.java Thu Mar 01 11:22:31 2018 +0100
@@ -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 @@
* <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 @@
* @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.
--- a/src/java.management/share/classes/java/lang/management/ThreadInfo.java Thu Mar 01 11:02:40 2018 +0100
+++ b/src/java.management/share/classes/java/lang/management/ThreadInfo.java Thu Mar 01 11:22:31 2018 +0100
@@ -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 @@
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 @@
/*
* 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 @@
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 @@
/**
* 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 @@
* - 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 @@
* 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};
--- a/src/java.management/share/classes/sun/management/LockInfoCompositeData.java Thu Mar 01 11:02:40 2018 +0100
+++ b/src/java.management/share/classes/sun/management/LockInfoCompositeData.java Thu Mar 01 11:22:31 2018 +0100
@@ -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 @@
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 @@
}
}
- 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 @@
}
}
- 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 @@
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");
}
--- a/src/java.management/share/classes/sun/management/MonitorInfoCompositeData.java Thu Mar 01 11:02:40 2018 +0100
+++ b/src/java.management/share/classes/sun/management/MonitorInfoCompositeData.java Thu Mar 01 11:22:31 2018 +0100
@@ -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.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 @@
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 @@
}
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 @@
}
}
- 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 @@
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");
}
--- a/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java Thu Mar 01 11:02:40 2018 +0100
+++ b/src/java.management/share/classes/sun/management/StackTraceElementCompositeData.java Thu Mar 01 11:22:31 2018 +0100
@@ -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 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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;
}
--- a/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java Thu Mar 01 11:02:40 2018 +0100
+++ b/src/java.management/share/classes/sun/management/ThreadInfoCompositeData.java Thu Mar 01 11:22:31 2018 +0100
@@ -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 @@
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 @@
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 @@
}
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
- // threadInfoItemNames!
+ // THREAD_INFO_ATTRIBUTES!
final Object[] threadInfoItemValues = {
threadInfo.getThreadId(),
threadInfo.getThreadName(),
@@ -126,8 +118,8 @@
threadInfo.getLockOwnerId(),
threadInfo.getLockOwnerName(),
stackTraceData,
- threadInfo.isSuspended(),
- threadInfo.isInNative(),
+ threadInfo.isSuspended(),
+ threadInfo.isInNative(),
lockedMonitorsData,
lockedSyncsData,
threadInfo.isDaemon(),
@@ -135,8 +127,8 @@
};
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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;
+ }
+
+ if (!isTypeMatched(ThreadInfoCompositeTypes.ofVersion(version), type)) {
+ throw new IllegalArgumentException(
+ "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);
}
}
- CompositeData[] stackTraceData =
- (CompositeData[]) cd.get(STACK_TRACE);
- if (stackTraceData == null) {
- throw new IllegalArgumentException(
- "StackTraceElement[] is missing");
- }
- if (stackTraceData.length > 0) {
- StackTraceElementCompositeData.validateCompositeData(stackTraceData[0]);
+ 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);
+ }
}
- // 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.");
+ 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;
}
- }
-
- CompositeData[] lms = (CompositeData[]) cd.get(LOCKED_MONITORS);
- if (lms == null) {
- throw new IllegalArgumentException("MonitorInfo[] is null");
+ return new CompositeType("ThreadInfo",
+ "JDK 6 ThreadInfo",
+ v6Names,
+ v6Names,
+ v6Types);
+ } catch (OpenDataException e) {
+ // Should never reach here
+ throw new AssertionError(e);
}
- 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.");
- }
- }
-
}
}
-
private static final long serialVersionUID = 2464378539119753175L;
}
--- a/src/java.management/share/classes/sun/management/TypeVersionMapper.java Thu Mar 01 11:02:40 2018 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -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);
- }
-}
--- a/test/jdk/java/lang/management/CompositeData/ThreadInfoCompositeData.java Thu Mar 01 11:02:40 2018 +0100
+++ b/test/jdk/java/lang/management/CompositeData/ThreadInfoCompositeData.java Thu Mar 01 11:22:31 2018 +0100
@@ -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 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);
+ }
+
+ /*
+ * 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");
+ }
+ 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);
}
- 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];
- }
- CompositeType ct =
- new CompositeType("MyCompositeType",
- "CompositeType for JDK 5.0 ThreadInfo",
- v5ItemNames,
- v5ItemNames,
- v5ItemTypes);
- CompositeData cd =
- new CompositeDataSupport(ct,
- v5ItemNames,
- v5ItemValues);
- ThreadInfo info = ThreadInfo.from(cd);
- checkThreadInfo(info);
- }
+ static void checkThreadInfoV5(ThreadInfo info) {
+ Object[] values = Factory.VALUES;
- static void checkThreadInfo(ThreadInfo info) throws Exception {
- if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) {
+ if (info.getThreadId() != ((Long) values[THREAD_ID]).longValue()) {
throw new RuntimeException("Thread Id = " + info.getThreadId() +
" expected = " + values[THREAD_ID]);
}
@@ -148,30 +193,35 @@
info.getLockOwnerName() + " expected = " +
values[LOCK_OWNER_NAME]);
}
+
+ 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]);
+ info.isDaemon() + " expected = " + values[DAEMON]);
}
-
- checkStackTrace(info.getStackTrace());
-
- checkLockInfo(info.getLockInfo());
}
- 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 @@
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 @@
}
}
- 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 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;
+
+ static class Factory {
- private static final String[] validItemNames = {
- "threadId",
- "threadName",
- "threadState",
- "blockedTime",
- "blockedCount",
- "waitedTime",
- "waitedCount",
- "lockName",
- "lockOwnerId",
- "lockOwnerName",
- "stackTrace",
- "suspended",
- "inNative",
- "lockInfo",
- "daemon",
- "priority",
- };
+ 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;
+
+ static {
+ CompositeType steCType = null;
+ CompositeType lockInfoCType = null;
+ CompositeType monitorInfoCType = null;
+ ArrayType steArrayType = null;
+ ArrayType lockInfoArrayType = null;
+ ArrayType monitorInfoArrayType = null;
- 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,
- };
+ 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;
+ }
+
+ 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);
+ }
- 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 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);
+ }
- private static final String[] steItemNames = {
- "classLoaderName",
- "moduleName",
- "moduleVersion",
- "className",
- "methodName",
- "fileName",
- "lineNumber",
- "nativeMethod",
- };
-
- private static final String[] lockInfoItemNames = {
- "className",
- "identityHashCode",
- };
-
- static {
- // create stack trace element
- ste[0] = new StackTraceElement("FooClass", "getFoo", "Foo.java", 100);
-
- // 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);
+
+ // Copy before mutating to avoid affecting other tests.
+ Object[] localValues = VALUES.clone();
+
+ // 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();
- CompositeType lockInfoCType = (CompositeType)
- OpenTypeConverter.toOpenType(LockInfo.class);
- validItemTypes[LOCK_INFO] = lockInfoCType;
+ 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();
- final Object[] lockInfoValue = {
+ 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,
- };
-
}
--- a/test/jdk/sun/management/StackTraceElementCompositeData/CompatibilityTest.java Thu Mar 01 11:02:40 2018 +0100
+++ b/test/jdk/sun/management/StackTraceElementCompositeData/CompatibilityTest.java Thu Mar 01 11:22:31 2018 +0100
@@ -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.CompositeType;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
+
import sun.management.StackTraceElementCompositeData;
import org.testng.annotations.*;
@@ -14,6 +37,7 @@
/*
* @test
* @bug 8139587
+ * @modules java.management/sun.management
* @summary Check backward compatibility of StackTraceElementCompositeData
* @author Jaroslav Bachorik
*
@@ -22,21 +46,33 @@
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 @@
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);
+
+ return new CompositeDataSupport(compositeTypeV6, itemsV6);
+ }
- compositeDataV6 = 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 @@
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);
+ }
}