JDK-8198253 : ThreadInfo.from(CompositeData) incorrectly accepts CompositeData with missing JDK 6 attributes
  • Type: Bug
  • Component: core-svc
  • Sub-Component: java.lang.management
  • Affected Version: 9.0.4
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2018-02-16
  • Updated: 2018-10-23
  • Resolved: 2018-03-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11
11 b04Fixed
Related Reports
CSR :  
Relates :  
Relates :  
Description
ThreadInfo.from(CompositeData) returns a new ThreadInfo, choosing the fields to instantiate based on whether the CompositeData contains the fields in a particular JDK release.  So, for example, if the CompositeData contains the fields for JDK 6, the fields for JDK 6 will be instantiated.  Here is the relevant code:

       // 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;
        }

The problem with this is that ticd.isCurrentVersion tests to make sure that *all* of the fields are present.  Two of the fields - lockedMonitors and lockedSynchronizers - are spec'd to be optional.  If the CompositeData is missing those two fields, the daemon and priority fields will not get set.

There is a test for this use case, but is assigns false to daemon and Thread.NORM_PRIORITY to priority, so the failure wasn't detected.
Comments
In addition to the above w.r.t. interoperability, "stackTrace" and "lockedMonitors" attribute should contain StackTraceElement of the same version of ThreadInfo.
23-02-2018

lockedMonitors and lockedSynchronizers attribute are not optional for JDK 6 and later releases. JMX client can connect to a running VM in any version and get back a proper ThreadInfo. lockedMonitors and lockedSynchronizers were added in JDK 6. ThreadInfo::from is specified to support CompositeData representing JDK 1.5 ThreadInfo in which lockedMonitors and lockedSynchronizers attribute are not present for interoperability. daemon and priority were added in JDK 9 (JDK-6588467). ThreadInfo::from will support the three different version: 1. CompositeData for JDK 1.5 ThreadInfo with no lockedMonitors and lockedSynchronizers attribute 2. CompositeData for JDK 6 ThreadInfo with lockedMonitors and lockedSynchronizers attributes 3. CompositeData for JDK 9 ThreadInfo with lockedMonitors and lockedSynchronizers attributes and with daemon and priority attribute. If ThreadInfo::from is called with a CompositeData containing daemon and priority attribute but lockedMonitors and lockedSynchronizers attributes are absent then the given CompositeData is invalid and IllegalArgumentException should be thrown. I think the specification should be clarified.
17-02-2018