Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8234305

ClassCastException when calling FlightRecorderMXBean#getRecordings()

    Details

    • Type: CSR
    • Status: Closed
    • Priority: P3
    • Resolution: Approved
    • Fix Version/s: 15
    • Component/s: hotspot
    • Labels:
      None
    • Subcomponent:
      jfr
    • Compatibility Risk:
      minimal
    • Compatibility Risk Description:
      The method RecordingInfo::from(CompositeData) method has not worked with the key that the javadoc states, so this change will not break existing code.
    • Interface Kind:
      Java API
    • Scope:
      JDK

      Description

      Summary

      Change the specification of the jdk.management.jfr.RecordingInfo::from(CompositeData) method so it states that the key "toDisk" (instead of "disk") should be used for deserialization.

      Problem

      The FlightRecorderMXBean::getRecordings() method returns a list of RecordingInfo objects containing information about available recordings. A recording can be persisted to disk or to memory, and users can invoke the RecordingInfo::isToDisk() method to find out which.

      When a RecordingInfo object is serialized as a CompositeData object, the key is derived from the method name and becomes "toDisk". The deserialization method RecordingInfo::from method on the other hand assumes the key is "disk", which means an InvalidKeyException is thrown. The deserialization method also assumes that the recording id is of type int, when it is a long, leading to a ClassCastException on the client. This happens before the InvalidKeyException is reached.

      Solution

      Change the implementation of the RecordingInfo class so that the recording id is deserialized as a long and use the key "toDisk" instead of "disk". At the same time, update the javadoc for the RecordingInfo::from method so it states that the key "toDisk" should be used.

      An alternative approach would be to change the implementation to match the javadoc, but that would cause problems for clients, such as JDK Mission Control, that already operates against the CompositeData and assumes the key is "toDisk".

      Specification

      src/jdk.management.jfr/share/classes/jdk/management/jfr/RecordingInfo.java

      @@ -51,7 +51,7 @@
           private final String state;
           private final boolean dumpOnExit;
           private final long size;
      -    private final boolean disk;
      +    private final boolean toDisk;
           private final long maxAge;
           private final long maxSize;
           private final long startTime;
      @@ -67,7 +67,7 @@
               state = recording.getState().toString();
               dumpOnExit = recording.getDumpOnExit();
               size = recording.getSize();
      -        disk = recording.isToDisk();
      +        toDisk = recording.isToDisk();
      
               Duration d = recording.getMaxAge();
               if (d == null) {
      @@ -87,12 +87,17 @@
           }
      
           private RecordingInfo(CompositeData cd) {
      -        id = (int) cd.get("id");
      +        id = (long) cd.get("id");
               name = (String) cd.get("name");
               state = (String) cd.get("state");
               dumpOnExit = (boolean) cd.get("dumpOnExit");
               size = (long) cd.get("size");
      -        disk = (boolean) cd.get("disk");
      +        if(cd.containsKey("toDisk")){
      +            toDisk = (boolean) cd.get("toDisk");
      +        } else {
      +            // Before JDK-8219904 was fixed, the element name was disk, so for compatibility
      +            toDisk = (boolean) cd.get("disk");
      +        }
               maxAge = (Long) cd.get("maxAge");
               maxSize = (Long) cd.get("maxSize");
               startTime = (Long) cd.get("startTime");
      @@ -290,7 +295,7 @@
            * @return {@code true} if recording is to disk, {@code false} otherwise
            */
           public boolean isToDisk() {
      -        return disk;
      +        return toDisk;
           }
      
           /**
      @@ -342,7 +347,7 @@
            * <td>{@code Long}</td>
            * </tr>
            * <tr>
      -     * <th scope="row">disk</th>
      +     * <th scope="row">toDisk</th>
            * <td>{@code Boolean}</td>
            * </tr>
            * <tr>

      For convenience the current webrev can be browsed here: http://cr.openjdk.java.net/~cito/JDK-8219904/webrev.03/

        Attachments

          Issue Links

            Activity

              People

              • Assignee:
                cito Chihiro Ito
                Reporter:
                webbuggrp Webbug Group
                Reviewed By:
                Erik Gahlin
              • Votes:
                0 Vote for this issue
                Watchers:
                1 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: