8212795: ThreadInfoCompositeData.toCompositeData fails to map ThreadInfo to CompositeData

Reviewed-by: dfuchs
This commit is contained in:
Mandy Chung 2018-10-25 10:57:42 -07:00
parent 85598bc90f
commit d523a17e80
5 changed files with 85 additions and 126 deletions

View File

@ -26,6 +26,7 @@
package sun.management; package sun.management;
import java.lang.management.LockInfo; import java.lang.management.LockInfo;
import java.util.Map;
import javax.management.openmbean.CompositeType; import javax.management.openmbean.CompositeType;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataSupport;
@ -57,17 +58,13 @@ public class LockInfoCompositeData extends LazyCompositeData {
} }
protected CompositeData getCompositeData() { protected CompositeData getCompositeData() {
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH Map<String,Object> items = Map.of(
// LOCK_INFO_ATTRIBUTES! CLASS_NAME, lock.getClassName(),
final Object[] lockInfoItemValues = { IDENTITY_HASH_CODE, lock.getIdentityHashCode()
new String(lock.getClassName()), );
lock.getIdentityHashCode(),
};
try { try {
return new CompositeDataSupport(LOCK_INFO_COMPOSITE_TYPE, return new CompositeDataSupport(LOCK_INFO_COMPOSITE_TYPE, items);
LOCK_INFO_ATTRIBUTES,
lockInfoItemValues);
} catch (OpenDataException e) { } catch (OpenDataException e) {
// Should never reach here // Should never reach here
throw Util.newException(e); throw Util.newException(e);
@ -91,10 +88,6 @@ public class LockInfoCompositeData extends LazyCompositeData {
private static final String CLASS_NAME = "className"; private static final String CLASS_NAME = "className";
private static final String IDENTITY_HASH_CODE = "identityHashCode"; private static final String IDENTITY_HASH_CODE = "identityHashCode";
private static final String[] LOCK_INFO_ATTRIBUTES = {
CLASS_NAME,
IDENTITY_HASH_CODE,
};
/* /*
* Returns a LockInfo object mapped from the given CompositeData. * Returns a LockInfo object mapped from the given CompositeData.

View File

@ -26,6 +26,8 @@
package sun.management; package sun.management;
import java.lang.management.MonitorInfo; import java.lang.management.MonitorInfo;
import java.util.HashMap;
import java.util.Map;
import javax.management.openmbean.CompositeType; import javax.management.openmbean.CompositeType;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataSupport;
@ -54,31 +56,18 @@ public class MonitorInfoCompositeData extends LazyCompositeData {
} }
protected CompositeData getCompositeData() { protected CompositeData getCompositeData() {
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH
// MONITOR_INFO_ATTRIBUTES!
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 = MONITOR_INFO_ATTRIBUTES[i];
if (item.equals(LOCKED_STACK_FRAME)) {
StackTraceElement ste = lock.getLockedStackFrame(); StackTraceElement ste = lock.getLockedStackFrame();
values[i] = (ste != null ? StackTraceElementCompositeData. CompositeData steCData = ste != null ? StackTraceElementCompositeData.toCompositeData(ste)
toCompositeData(ste) : null;
: null); // values may be null; can't use Map.of
} else if (item.equals(LOCKED_STACK_DEPTH)) { Map<String,Object> items = new HashMap<>();
values[i] = lock.getLockedStackDepth(); items.put(CLASS_NAME, lock.getClassName());
} else { items.put(IDENTITY_HASH_CODE, lock.getIdentityHashCode());
values[i] = li.get(item); items.put(LOCKED_STACK_FRAME, steCData);
} items.put(LOCKED_STACK_DEPTH, lock.getLockedStackDepth());
}
try { try {
return new CompositeDataSupport(MONITOR_INFO_COMPOSITE_TYPE, return new CompositeDataSupport(MONITOR_INFO_COMPOSITE_TYPE, items);
MONITOR_INFO_ATTRIBUTES,
values);
} catch (OpenDataException e) { } catch (OpenDataException e) {
// Should never reach here // Should never reach here
throw new AssertionError(e); throw new AssertionError(e);
@ -126,10 +115,6 @@ public class MonitorInfoCompositeData extends LazyCompositeData {
return V6_COMPOSITE_TYPE; return V6_COMPOSITE_TYPE;
} }
static CompositeType compositeType() {
return MONITOR_INFO_COMPOSITE_TYPE;
}
public static String getClassName(CompositeData cd) { public static String getClassName(CompositeData cd) {
return getString(cd, CLASS_NAME); return getString(cd, CLASS_NAME);
} }

View File

@ -31,6 +31,8 @@ import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType; import javax.management.openmbean.OpenType;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream; import java.util.stream.Stream;
/** /**
@ -75,24 +77,19 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
} }
protected CompositeData getCompositeData() { protected CompositeData getCompositeData() {
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH // values may be null; so can't use Map.of
// STACK_TRACE_ELEMENT_ATTRIBUTES! Map<String,Object> items = new HashMap<>();
final Object[] stackTraceElementItemValues = { items.put(CLASS_LOADER_NAME, ste.getClassLoaderName());
// JDK 5 attributes items.put(MODULE_NAME, ste.getModuleName());
ste.getClassName(), items.put(MODULE_VERSION, ste.getModuleVersion());
ste.getMethodName(), items.put(CLASS_NAME, ste.getClassName());
ste.getFileName(), items.put(METHOD_NAME, ste.getMethodName());
ste.getLineNumber(), items.put(FILE_NAME, ste.getFileName());
ste.isNativeMethod(), items.put(LINE_NUMBER, ste.getLineNumber());
// JDK 9 attributes items.put(NATIVE_METHOD, ste.isNativeMethod());
ste.getClassLoaderName(),
ste.getModuleName(),
ste.getModuleVersion(),
};
try { try {
return new CompositeDataSupport(STACK_TRACE_ELEMENT_COMPOSITE_TYPE, return new CompositeDataSupport(STACK_TRACE_ELEMENT_COMPOSITE_TYPE, items);
STACK_TRACE_ELEMENT_ATTRIBUTES,
stackTraceElementItemValues);
} catch (OpenDataException e) { } catch (OpenDataException e) {
// Should never reach here // Should never reach here
throw new AssertionError(e); throw new AssertionError(e);
@ -123,10 +120,6 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
MODULE_VERSION, MODULE_VERSION,
}; };
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 STACK_TRACE_ELEMENT_COMPOSITE_TYPE;
private static final CompositeType V5_COMPOSITE_TYPE; private static final CompositeType V5_COMPOSITE_TYPE;
static { static {
@ -153,9 +146,6 @@ public class StackTraceElementCompositeData extends LazyCompositeData {
static CompositeType v5CompositeType() { static CompositeType v5CompositeType() {
return V5_COMPOSITE_TYPE; return V5_COMPOSITE_TYPE;
} }
static CompositeType compositeType() {
return STACK_TRACE_ELEMENT_COMPOSITE_TYPE;
}
/** /**
* Validate if the input CompositeData has the expected * Validate if the input CompositeData has the expected

View File

@ -75,8 +75,7 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
protected CompositeData getCompositeData() { protected CompositeData getCompositeData() {
// Convert StackTraceElement[] to CompositeData[] // Convert StackTraceElement[] to CompositeData[]
StackTraceElement[] stackTrace = threadInfo.getStackTrace(); StackTraceElement[] stackTrace = threadInfo.getStackTrace();
CompositeData[] stackTraceData = CompositeData[] stackTraceData = new CompositeData[stackTrace.length];
new CompositeData[stackTrace.length];
for (int i = 0; i < stackTrace.length; i++) { for (int i = 0; i < stackTrace.length; i++) {
StackTraceElement ste = stackTrace[i]; StackTraceElement ste = stackTrace[i];
stackTraceData[i] = StackTraceElementCompositeData.toCompositeData(ste); stackTraceData[i] = StackTraceElementCompositeData.toCompositeData(ste);
@ -88,48 +87,42 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
// Convert LockInfo[] and MonitorInfo[] to CompositeData[] // Convert LockInfo[] and MonitorInfo[] to CompositeData[]
LockInfo[] lockedSyncs = threadInfo.getLockedSynchronizers(); LockInfo[] lockedSyncs = threadInfo.getLockedSynchronizers();
CompositeData[] lockedSyncsData = CompositeData[] lockedSyncsData = new CompositeData[lockedSyncs.length];
new CompositeData[lockedSyncs.length];
for (int i = 0; i < lockedSyncs.length; i++) { for (int i = 0; i < lockedSyncs.length; i++) {
LockInfo li = lockedSyncs[i]; LockInfo li = lockedSyncs[i];
lockedSyncsData[i] = LockInfoCompositeData.toCompositeData(li); lockedSyncsData[i] = LockInfoCompositeData.toCompositeData(li);
} }
MonitorInfo[] lockedMonitors = threadInfo.getLockedMonitors(); MonitorInfo[] lockedMonitors = threadInfo.getLockedMonitors();
CompositeData[] lockedMonitorsData = CompositeData[] lockedMonitorsData = new CompositeData[lockedMonitors.length];
new CompositeData[lockedMonitors.length];
for (int i = 0; i < lockedMonitors.length; i++) { for (int i = 0; i < lockedMonitors.length; i++) {
MonitorInfo mi = lockedMonitors[i]; MonitorInfo mi = lockedMonitors[i];
lockedMonitorsData[i] = MonitorInfoCompositeData.toCompositeData(mi); lockedMonitorsData[i] = MonitorInfoCompositeData.toCompositeData(mi);
} }
// CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH // values may be null; can't use Map.of
// THREAD_INFO_ATTRIBUTES! Map<String,Object> items = new HashMap<>();
final Object[] threadInfoItemValues = { items.put(THREAD_ID, threadInfo.getThreadId());
threadInfo.getThreadId(), items.put(THREAD_NAME, threadInfo.getThreadName());
threadInfo.getThreadName(), items.put(THREAD_STATE, threadInfo.getThreadState().name());
threadInfo.getThreadState().name(), items.put(BLOCKED_TIME, threadInfo.getBlockedTime());
threadInfo.getBlockedTime(), items.put(BLOCKED_COUNT, threadInfo.getBlockedCount());
threadInfo.getBlockedCount(), items.put(WAITED_TIME, threadInfo.getWaitedTime());
threadInfo.getWaitedTime(), items.put(WAITED_COUNT, threadInfo.getWaitedCount());
threadInfo.getWaitedCount(), items.put(LOCK_INFO, lockInfoData);
lockInfoData, items.put(LOCK_NAME, threadInfo.getLockName());
threadInfo.getLockName(), items.put(LOCK_OWNER_ID, threadInfo.getLockOwnerId());
threadInfo.getLockOwnerId(), items.put(LOCK_OWNER_NAME, threadInfo.getLockOwnerName());
threadInfo.getLockOwnerName(), items.put(STACK_TRACE, stackTraceData);
stackTraceData, items.put(SUSPENDED, threadInfo.isSuspended());
threadInfo.isSuspended(), items.put(IN_NATIVE, threadInfo.isInNative());
threadInfo.isInNative(), items.put(LOCKED_MONITORS, lockedMonitorsData);
lockedMonitorsData, items.put(LOCKED_SYNCS, lockedSyncsData);
lockedSyncsData, items.put(DAEMON, threadInfo.isDaemon());
threadInfo.isDaemon(), items.put(PRIORITY, threadInfo.getPriority());
threadInfo.getPriority(),
};
try { try {
return new CompositeDataSupport(compositeType(), return new CompositeDataSupport(ThreadInfoCompositeTypes.ofVersion(RUNTIME_VERSION), items);
THREAD_INFO_ATTRIBTUES,
threadInfoItemValues);
} catch (OpenDataException e) { } catch (OpenDataException e) {
// Should never reach here // Should never reach here
throw new AssertionError(e); throw new AssertionError(e);
@ -183,10 +176,6 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
PRIORITY, PRIORITY,
}; };
private static final String[] THREAD_INFO_ATTRIBTUES =
Stream.of(V5_ATTRIBUTES, V6_ATTRIBUTES, V9_ATTRIBUTES)
.flatMap(Arrays::stream).toArray(String[]::new);
public long threadId() { public long threadId() {
return getLong(cdata, THREAD_ID); return getLong(cdata, THREAD_ID);
} }
@ -365,12 +354,8 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
} }
} }
public static CompositeType compositeType() { static final int RUNTIME_VERSION = Runtime.version().feature();
return ThreadInfoCompositeTypes.compositeTypes.get(0);
}
static class ThreadInfoCompositeTypes { static class ThreadInfoCompositeTypes {
static final int CURRENT = Runtime.version().feature();
static final Map<Integer, CompositeType> compositeTypes = initCompositeTypes(); static final Map<Integer, CompositeType> compositeTypes = initCompositeTypes();
/* /*
* Returns CompositeType of the given runtime version * Returns CompositeType of the given runtime version
@ -382,7 +367,7 @@ public class ThreadInfoCompositeData extends LazyCompositeData {
static Map<Integer, CompositeType> initCompositeTypes() { static Map<Integer, CompositeType> initCompositeTypes() {
Map<Integer, CompositeType> types = new HashMap<>(); Map<Integer, CompositeType> types = new HashMap<>();
CompositeType ctype = initCompositeType(); CompositeType ctype = initCompositeType();
types.put(CURRENT, ctype); types.put(RUNTIME_VERSION, ctype);
types.put(5, initV5CompositeType(ctype)); types.put(5, initV5CompositeType(ctype));
types.put(6, initV6CompositeType(ctype)); types.put(6, initV6CompositeType(ctype));
return types; return types;

View File

@ -29,8 +29,9 @@
* the input CompositeData is invalid. * the input CompositeData is invalid.
* @author Mandy Chung * @author Mandy Chung
* *
* @modules java.management/sun.management
* @build ThreadInfoCompositeData OpenTypeConverter * @build ThreadInfoCompositeData OpenTypeConverter
* @run main ThreadInfoCompositeData * @run testng/othervm ThreadInfoCompositeData
*/ */
@ -42,6 +43,9 @@ import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.testng.annotations.Test;
import static org.testng.Assert.*;
public class ThreadInfoCompositeData { public class ThreadInfoCompositeData {
private static String lockClassName = "myClass"; private static String lockClassName = "myClass";
private static int lockIdentityHashCode = 123456; private static int lockIdentityHashCode = 123456;
@ -50,24 +54,7 @@ public class ThreadInfoCompositeData {
private static LockInfo lockInfo = private static LockInfo lockInfo =
new LockInfo(lockClassName, lockIdentityHashCode); new LockInfo(lockClassName, lockIdentityHashCode);
public static void main(String[] argv) throws Exception { @Test
// A valid CompositeData is passed to ThreadInfo
createGoodCompositeData();
// 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 { public static void createGoodCompositeData() throws Exception {
CompositeData cd = Factory.makeThreadInfoCompositeData(); CompositeData cd = Factory.makeThreadInfoCompositeData();
ThreadInfo info = ThreadInfo.from(cd); ThreadInfo info = ThreadInfo.from(cd);
@ -77,6 +64,7 @@ public class ThreadInfoCompositeData {
/* /*
* An invalid CompositeData with JDK 9 attributes but missing JDK 6 attributes * An invalid CompositeData with JDK 9 attributes but missing JDK 6 attributes
*/ */
@Test
public static void badMissingCompositeData() throws Exception { public static void badMissingCompositeData() throws Exception {
CompositeData cd = Factory.makeCompositeDataMissingV6(); CompositeData cd = Factory.makeCompositeDataMissingV6();
try { try {
@ -92,6 +80,7 @@ public class ThreadInfoCompositeData {
/* /*
* Current version of ThreadInfo but an older version of StackTraceElement * Current version of ThreadInfo but an older version of StackTraceElement
*/ */
@Test
public static void withV5StackTraceCompositeData() throws Exception { public static void withV5StackTraceCompositeData() throws Exception {
CompositeData cd = Factory.makeThreadInfoWithV5StackTrace(); CompositeData cd = Factory.makeThreadInfoWithV5StackTrace();
try { try {
@ -104,6 +93,7 @@ public class ThreadInfoCompositeData {
* Current version of ThreadInfo but an older version of MonitorInfo * Current version of ThreadInfo but an older version of MonitorInfo
* and the value of "lockedStackFrame" attribute is null. * and the value of "lockedStackFrame" attribute is null.
*/ */
@Test
public static void withInvalidMonitorInfoCompositeData() throws Exception { public static void withInvalidMonitorInfoCompositeData() throws Exception {
CompositeData cd = Factory.makeThreadInfoWithIncompatibleMonitorInfo(); CompositeData cd = Factory.makeThreadInfoWithIncompatibleMonitorInfo();
@ -128,6 +118,7 @@ public class ThreadInfoCompositeData {
/* /*
* ThreadInfo of version N can accept lockedMonitors of version >= N * ThreadInfo of version N can accept lockedMonitors of version >= N
*/ */
@Test
public static void withNewMonitorInfoCompositeData() throws Exception { public static void withNewMonitorInfoCompositeData() throws Exception {
CompositeData cd = Factory.makeThreadInfoWithNewMonitorInfo(); CompositeData cd = Factory.makeThreadInfoWithNewMonitorInfo();
ThreadInfo info = ThreadInfo.from(cd); ThreadInfo info = ThreadInfo.from(cd);
@ -137,12 +128,25 @@ public class ThreadInfoCompositeData {
/* /*
* Test CompositeData representing JDK 5 ThreadInfo * Test CompositeData representing JDK 5 ThreadInfo
*/ */
@Test
public static void createV5ThreadInfo() throws Exception { public static void createV5ThreadInfo() throws Exception {
CompositeData cd = Factory.makeThreadInfoV5CompositeData(); CompositeData cd = Factory.makeThreadInfoV5CompositeData();
ThreadInfo info = ThreadInfo.from(cd); ThreadInfo info = ThreadInfo.from(cd);
checkThreadInfoV5(info); checkThreadInfoV5(info);
} }
/*
* Test ThreadInfoCompositeData.toCompositeData
*/
@Test
public static void internalToCompositeData() throws Exception {
CompositeData cd = Factory.makeThreadInfoCompositeData();
ThreadInfo info = ThreadInfo.from(cd);
cd = sun.management.ThreadInfoCompositeData.toCompositeData(info);
info = ThreadInfo.from(cd);
checkThreadInfo(info);
}
static void checkThreadInfoV5(ThreadInfo info) { static void checkThreadInfoV5(ThreadInfo info) {
Object[] values = Factory.VALUES; Object[] values = Factory.VALUES;
@ -262,6 +266,7 @@ public class ThreadInfoCompositeData {
} }
} }
@Test
public static void badNameCompositeData() throws Exception { public static void badNameCompositeData() throws Exception {
CompositeData cd = Factory.makeCompositeDataWithBadNames(); CompositeData cd = Factory.makeCompositeDataWithBadNames();
try { try {
@ -270,6 +275,7 @@ public class ThreadInfoCompositeData {
} catch (IllegalArgumentException e) { } } catch (IllegalArgumentException e) { }
} }
@Test
public static void badTypeCompositeData() throws Exception { public static void badTypeCompositeData() throws Exception {
CompositeData cd = Factory.makeCompositeDataWithBadTypes(); CompositeData cd = Factory.makeCompositeDataWithBadTypes();
@ -300,7 +306,7 @@ public class ThreadInfoCompositeData {
private static final int DAEMON = 16; private static final int DAEMON = 16;
private static final int PRIORITY = 17; private static final int PRIORITY = 17;
static class Factory { private static class Factory {
static final CompositeType STE_COMPOSITE_TYPE; static final CompositeType STE_COMPOSITE_TYPE;
static final CompositeType LOCK_INFO_COMPOSITE_TYPE; static final CompositeType LOCK_INFO_COMPOSITE_TYPE;