0

我使用以下代码来开始 JFR 记录并将结果保存在文件中。该文件确实已创建,但如何解析它?我认为它应该是 jfr 文件类型,但 jdk.jfr.consumer.RecordingFile 无法解析它(“java.io.IOException:不是飞行记录器文件”)。任何帮助/示例将不胜感激。

    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();
    
4

1 回答 1

1

问题是您不会为第一次读取写入数据。

以下代码有效:

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

或者您可以使用 JDK 17,其中已将转储方法添加到 RemoteRecordingStream 并同时避免使用 FlightRecorderMXBean。

try (var rrs = new RemoteRecordingStream(connection)) {
  rrs.start();
  rrs.stop();
  rrs.dump(Path.of("recording.jfr");
}
于 2021-07-01T12:34:45.980 回答