user9517026
user9517026

Reputation: 123

Reading and parsing stream from FlightRecorderMXBean

I use the following code in order to start JFR recording and to save results in file. The file is indeed created, but how to parse it? I thought it should be jfr file type, but jdk.jfr.consumer.RecordingFile fails to parse it ("java.io.IOException: Not a Flight Recorder file"). Any help/examples will be appreciated.

    String host = "localhost";
    int port = 9999;
    String s = "/jndi/rmi://" + host + ":" + port + "/jmxrmi";
    JMXServiceURL url = new JMXServiceURL("rmi", "", 0, s);
    JMXConnector jmxConnector = JMXConnectorFactory.newJMXConnector(url, null);
    jmxConnector.connect();
    MBeanServerConnection mbeanConnection = jmxConnector.getMBeanServerConnection();
    FlightRecorderMXBean frb = JMX.newMXBeanProxy(mbeanConnection, new ObjectName("jdk.management.jfr:type=FlightRecorder"),
            FlightRecorderMXBean.class);

    long recId = frb.newRecording();

    System.out.println("RECORDING STARTED");
    frb.startRecording(recId);
    Thread.sleep(60000);
    frb.stopRecording(recId);
    System.out.println("RECORDING ENDED");
            
    long streamId = frb.openStream(recId, null);

    FileOutputStream fw = new FileOutputStream("./jfrstream_" + recId);
    byte[] buff = frb.readStream(streamId);
    while (buff != null)
    {
        buff = frb.readStream(streamId);
        if (buff != null)
        {
            //System.out.println("buff.length=" + buff.length);
            fw.write(buff);
        }
    }
    frb.closeStream(streamId);
    fw.flush();
    fw.close();
    

Upvotes: 0

Views: 401

Answers (1)

Kire Haglin
Kire Haglin

Reputation: 7069

The problem is that you don't write the data for the first read.

The following code works:

File dump(long streamId, FlightRecorderMXBean bean) throws IOException {
  File f = new File("stream_" + streamId + ".jfr");
  try (var fos = new FileOutputStream(f); var bos = new BufferedOutputStream(fos)) {
    while (true) {
      byte[] data = bean.readStream(streamId);
       if (data == null) {
         bos.flush();
         return f;
       }
       bos.write(data);
    }
  }
}

Or you can use JDK 17, where a dump method has been added to RemoteRecordingStream and avoid the FlightRecorderMXBean all together.

try (var rrs = new RemoteRecordingStream(connection)) {
  rrs.start();
  rrs.stop();
  rrs.dump(Path.of("recording.jfr");
}

Upvotes: 1

Related Questions