1 /* 2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.management.jfr; 27 28 import java.io.IOException; 29 import java.lang.management.PlatformManagedObject; 30 import java.time.Instant; 31 import java.util.List; 32 import java.util.Map; 33 34 import jdk.jfr.Configuration; 35 import jdk.jfr.EventType; 36 import jdk.jfr.Recording; 37 38 /** 39 * Management interface for controlling Flight Recorder. 40 * <p> 41 * The object name for identifying the MXBean in the platform MBean 42 * server is: <blockquote> {@code jdk.management.jfr:type=FlightRecorder} </blockquote> 43 * <p> 44 * Flight Recorder can be configured in the following ways. There are 45 * <ul> 46 * <li><b>Recording options</b><br> 47 * Specify how long a recording should last, and where and when data 48 * should be dumped.</li> 49 * <li><b>Settings</b><br> 50 * Specify which events should be enabled and what kind information each 51 * event should capture.</li> 52 * <li><b>Configurations</b><br> 53 * Predefined sets of settings, typically derived from a settings file, 54 * that specify the configuration of multiple events simultaneously.</li> 55 * </ul> 56 * <p> 57 * See the package {@code jdk.jfr} documentation for descriptions of the settings 58 * syntax and the {@link ConfigurationInfo} for configuration related information.. 59 * 60 * <h3>Recording options</h3> 61 * <p> 62 * The following table shows the options names to use with {@link #setRecordingOptions(long, Map)} 63 * and {@link #getRecordingOptions(long)}. 64 * 65 * <table class="striped"> 66 * <caption>Recording options</caption> 67 * <thead> 68 * <tr> 69 * <th scope="col">Name</th> 70 * <th scope="col">Descripion</th> 71 * <th scope="col">Default value</th> 72 * <th scope="col">Format</th> 73 * <th scope="col">Example values</th> 74 * </tr> 75 * </thead> 76 * <tbody> 77 * <tr> 78 * <th scope="row">{@code name}</th> 79 * <td>Sets a human-readable recording name</td> 80 * <td>String representation of the recording id</td> 81 * <td>{@code String}</td> 82 * <td>{@code "My Recording"}, <br> 83 * {@code "profiling"}</td> 84 * </tr> 85 * <tr> 86 * <th scope="row">{@code maxAge}</th> 87 * <td>Specify the length of time that the data is kept in the disk repository until the 88 * oldest data may be deleted. Only works if {@code disk=true}, otherwise 89 * this parameter is ignored.</td> 90 * <td>{@code "0"} (no limit)</td> 91 * <td>{@code "0"} if no limit is imposed, otherwise a string 92 * representation of a positive {@code Long} value followed by an empty space 93 * and one of the following units,<br> 94 * <br> 95 * {@code "ns"} (nanoseconds)<br> 96 * {@code "us"} (microseconds)<br> 97 * {@code "ms"} (milliseconds)<br> 98 * {@code "s"} (seconds)<br> 99 * {@code "m"} (minutes)<br> 100 * {@code "h"} (hours)<br> 101 * {@code "d"} (days)<br> 102 * </td> 103 * <td>{@code "2 h"},<br> 104 * {@code "24 h"},<br> 105 * {@code "2 d"},<br> 106 * {@code "0"}</td> 107 * </tr> 108 * <tr> 109 * <th scope="row">{@code maxSize}</th> 110 * <td>Specifies the size, measured in bytes, at which data is kept in disk 111 * repository. Only works if 112 * {@code disk=true}, otherwise this parameter is ignored.</td> 113 * <td>{@code "0"} (no limit)</td> 114 * <td>String representation of a {@code Long} value, must be positive</td> 115 * <td>{@code "0"}, <br> 116 * {@code "1000000000"}</td> 117 * </tr> 118 * <tr> 119 * <th scope="row">{@code dumpOnExit}</th> 120 * <td>Dumps recording data to disk on Java Virtual Machine (JVM) exit</td> 121 * <td>{@code "false"}</td> 122 * <td>String representation of a {@code Boolean} value, {@code "true"} or 123 * {@code "false"}</td> 124 * <td>{@code "true"},<br> 125 * {@code "false"}</td> 126 * </tr> 127 * <tr> 128 * <th scope="row">{@code destination}</th> 129 * <td>Specifies the Path where recording data is written when the recording stops.</td> 130 * <td>{@code "false"}</td> 131 * <td>See {@code Paths#getPath} for format. <br> 132 * If this method is invoked from another process, the data is written on the 133 * machine where the target VM is running. If destination is a relative path, it 134 * is relative to the working directory where the target VM was started.}</td> 135 * <td>{@code "c:\recording\recotding.jfr"},<br> 136 * {@code "/recordings/recording.jfr"}, {@code "recording.jfr"}</td> 137 * </tr> 138 * <tr> 139 * <th scope="row">{@code disk}</th> 140 * <td>Stores recorded data as it is recorded</td> 141 * <td><code>"false"</code></td> 142 * <td>String representation of a {@code Boolean} value, {@code "true"} or 143 * {@code "false"}</td> 144 * <td>{@code "true"},<br> 145 * {@code "false"}</td> 146 * <tr> 147 * <th scope="row">{@code duration}</th> 148 * <td>Sets how long the recording should be running</td> 149 * <td>{@code "0"} (no limit, continuous)</td> 150 * <td>{@code "0"} if no limit should be imposed, otherwise a string 151 * representation of a positive {@code Long} followed by an empty space and one 152 * of the following units:<br> 153 * <br> 154 * {@code "ns"} (nanoseconds)<br> 155 * {@code "us"} (microseconds)<br> 156 * {@code "ms"} (milliseconds)<br> 157 * {@code "s"} (seconds)<br> 158 * {@code "m"} (minutes)<br> 159 * {@code "h"} (hours)<br> 160 * {@code "d"} (days)<br> 161 * </td> 162 * <td>{@code "60 s"},<br> 163 * {@code "10 m"},<br> 164 * {@code "4 h"},<br> 165 * {@code "0"}</td> 166 * </tr> 167 * </tbody> 168 * </table> 169 * 170 * @since 9 171 */ 172 public interface FlightRecorderMXBean extends PlatformManagedObject { 173 /** 174 * String representation of the {@code ObjectName} for the 175 * {@code FlightRecorderMXBean}. 176 */ 177 public static final String MXBEAN_NAME = "jdk.management.jfr:type=FlightRecorder"; 178 179 /** 180 * Creates a recording, but doesn't start it. 181 * 182 * @return a unique identifier that can be used to start, stop, close and 183 * configure the recording 184 * 185 * @throws IllegalStateException if Flight Recorder can't be started (for 186 * example, if the Java Virtual Machine (JVM) lacks Flight Recorder 187 * support). 188 * @throws java.lang.SecurityException if a security manager exists and the 189 * caller does not have {@code ManagementPermission("control")} 190 * 191 * @see Recording 192 */ 193 long newRecording() throws IllegalStateException, SecurityException; 194 195 /** 196 * Creates a snapshot recording of all available recorded data. 197 * <p> 198 * A snapshot is a synthesized recording in a stopped state. If no data is 199 * available, a recording with size {@code 0} is returned. 200 * <p> 201 * A snapshot provides stable access to data for later operations (for example, 202 * operations to change the time interval or to reduce the data size). 203 * <p> 204 * The caller must close the recording when access to the data is no longer 205 * needed. 206 * 207 * @return a snapshot of all available recording data, not {@code null} 208 * 209 * @throws java.lang.SecurityException if a security manager exists and the 210 * caller does not have {@code ManagementPermission("control")} 211 * 212 * @return a unique identifier that can be used for reading recording data. 213 * 214 * @see RecordingT 215 */ 216 public long takeSnapshot(); 217 218 /** 219 * Creates a copy of an existing recording, useful for extracting parts of a 220 * recording. 221 * <p> 222 * The cloned recording contains the same recording data as the 223 * original, but it has a new ID and a name prefixed with 224 * {@code "Clone of recording"}. If the original recording is running, then 225 * the clone is also running. 226 * 227 * @param recordingId the recording ID of the recording to create a clone 228 * from 229 * 230 * @param stop if the newly created clone is stopped before 231 * returning. 232 * 233 * @return a unique identifier that can be used to start, stop, 234 * close and configure the recording 235 * 236 * @throws IllegalArgumentException if a recording with the specified ID 237 * doesn't exist 238 * 239 * @throws java.lang.SecurityException if a security manager exists and the 240 * caller does not have {@code ManagementPermission("control")} 241 * 242 * @see Recording 243 */ 244 long cloneRecording(long recordingId, boolean stop) throws IllegalArgumentException, SecurityException; 245 246 /** 247 * Starts the recording with the specified ID. 248 * <p> 249 * A recording that is stopped can't be restarted. 250 * 251 * @param recordingId ID of the recording to start 252 * 253 * @throws IllegalArgumentException if a recording with the specified ID 254 * doesn't exist 255 * 256 * @throws java.lang.SecurityException if a security manager exists and the 257 * caller does not have {@code ManagementPermission("control")} 258 * 259 * @see Recording 260 */ 261 void startRecording(long recordingId) throws IllegalStateException, SecurityException; 262 263 /** 264 * Stops the running recording with the specified ID. 265 * 266 * @param recordingId the ID of the recording to stop 267 * 268 * @return {@code true} if the recording is stopped, {@code false} 269 * otherwise 270 * 271 * @throws IllegalArgumentException if a recording with the specified ID 272 * doesn't exist 273 * @throws IllegalStateException if the recording is not running 274 * @throws java.lang.SecurityException if a security manager exists and the 275 * caller does not have {@code ManagementPermission("control")} 276 * 277 * @see #newRecording() 278 */ 279 boolean stopRecording(long recordingId) throws IllegalArgumentException, IllegalStateException, SecurityException; 280 281 /** 282 * Closes the recording with the specified ID and releases any system 283 * resources that are associated with the recording. 284 * <p> 285 * If the recording is already closed, invoking this method has no effect. 286 * 287 * @param recordingId the ID of the recording to close 288 * 289 * @throws IllegalArgumentException if a recording with the specified ID 290 * doesn't exist 291 * @throws IOException if an I/O error occurs 292 * @throws java.lang.SecurityException if a security manager exists and the 293 * caller does not have {@code ManagementPermission("control")} 294 * 295 * @see #newRecording() 296 */ 297 void closeRecording(long recordingId) throws IOException; 298 299 /** 300 * Opens a data stream for the recording with the specified id, or {@code 0} 301 * to get data irrespective of recording. 302 * <table class="striped"> 303 * <caption>Recording stream options</caption> 304 * <thead> 305 * <tr> 306 * <th scope="col">Name</th> 307 * <th scope="col">Descripion</th> 308 * <th scope="col">Default value</th> 309 * <th scope="col">Format</th> 310 * <th scope="col">Example values</th> 311 * </tr> 312 * </thead> 313 * <tbody> 314 * <tr> 315 * <th scope="row">{@code startTime}</th> 316 * <td>Specifies the point in time to start a recording stream. Due to 317 * how data is stored, some events that start or end prior to the 318 * start time may be included.</td> 319 * <td>{@code Instant.MIN_VALUE.toString()}</td> 320 * <td>ISO-8601. See {@link Instant#toString}<br> 321 * or milliseconds since epoch</td> 322 * <td>{@code "2015-11-03T00:00"},<br> 323 * {@code "1446508800000"}</td> 324 * </tr> 325 * <tr> 326 * <th scope="row">{@code endTime}</th> 327 * <td>Specifies the point in time to end a recording stream. Due to how 328 * data is stored, some events that start or end after the end time may 329 * be included.</td> 330 * <td>{@code Instant.MAX_VALUE.toString()}</td> 331 * <td>ISO-8601. See {@link Instant#toString} <br> 332 * or milliseconds since epoch</td> 333 * <td>{@code "2015-11-03T01:00"}, <br> 334 * {@code "1446512400000"}</td> 335 * </tr> 336 * 337 * <tr> 338 * <th scope="row">{@code blockSize}</th> 339 * <td>Specifies the maximum number of bytes to read with a call to {@code readStream} 340 * </td> 341 * <td>{@code "50000"}</td> 342 * <td>A positive {@code long} value. <br> 343 * <br> 344 * Setting {@code blockSize} to a very high value may result in 345 * {@link OutOfMemoryError} or an {@link IllegalArgumentException}, if the 346 * Java Virtual Machine (JVM) deems the value too large to handle.</td> 347 * <td>{@code "50000"},<br> 348 * {@code "1000000"},<br> 349 * </tr> 350 * </tbody> 351 * </table> 352 * If an option is omitted from the map the default value is used. 353 * <p> 354 * The recording with the specified ID must be stopped before a stream can 355 * be opened. This restriction might be lifted in future releases. 356 * 357 * @param recordingId ID of the recording to open the stream for 358 * 359 * @param streamOptions a map that contains the options that controls the amount of data 360 * and how it is read, or {@code null} to get all data for the 361 * recording with the default block size 362 * 363 * @return a unique identifier for the stream. 364 * 365 * @throws IllegalArgumentException if a recording with the iD doesn't 366 * exist, or if {@code options} contains invalid values 367 * 368 * @throws IOException if the recording is closed, an I/O error occurs, or 369 * no data is available for the specified recording or 370 * interval 371 * 372 * @throws java.lang.SecurityException if a security manager exists and the 373 * caller does not have {@code ManagementPermission("control")} 374 */ 375 long openStream(long recordingId, Map<String, String> streamOptions) throws IOException; 376 377 /** 378 * Closes the recording stream with the specified ID and releases any system 379 * resources that are associated with the stream. 380 * <p> 381 * If the stream is already closed, invoking this method has no effect. 382 * 383 * @param streamId the ID of the stream 384 * 385 * @throws IllegalArgumentException if a stream with the specified ID doesn't 386 * exist 387 * @throws IOException if an I/O error occurs while trying to close the stream 388 * @throws java.lang.SecurityException if a security manager exists and the 389 * caller does not have {@code ManagementPermission("control")} 390 * 391 * @see #openStream(long, Map) 392 */ 393 void closeStream(long streamId) throws IOException; 394 395 /** 396 * Reads a portion of data from the stream with the specified ID, or returns 397 * {@code null} if no more data is available. 398 * <p> 399 * To read all data for a recording, invoke this method repeatedly until 400 * {@code null} is returned. 401 * 402 * @param streamId the ID of the stream 403 * 404 * @return byte array that contains recording data, or {@code null} when no more 405 * data is available 406 * @throws IOException if the stream is closed, or an I/O error occurred while 407 * trying to read the stream 408 * @throws IllegalArgumentException if no recording with the stream ID exists 409 * @throws java.lang.SecurityException if a security manager exists and the 410 * caller does not have {@code ManagementPermission("monitor")} 411 */ 412 byte[] readStream(long streamId) throws IOException; 413 414 /** 415 * Returns a map that contains the options for the recording with the 416 * specified ID (for example, the destination file or time span to keep 417 * recorded data). 418 * <p> 419 * See {@link FlightRecorderMXBean} for available option names. 420 * 421 * @param recordingId the ID of the recording to get options for 422 * 423 * @return a map describing the recording options, not {@code null} 424 * 425 * @throws IllegalArgumentException if no recording with the 426 * specified Id exists 427 * @throws java.lang.SecurityException if a security manager exists and the 428 * caller does not have {@code ManagementPermission("monitor")} 429 * 430 */ 431 Map<String, String> getRecordingOptions(long recordingId) throws IllegalArgumentException; 432 433 /** 434 * Returns a map that contains the settings for the recording with the specified ID, 435 * (for example, the event thresholds) 436 * <p> 437 * If multiple recordings are running at the same time, more data could be 438 * recorded than what is specified in this map. 439 * <p> 440 * The name in the map is the event name and the setting name separated by 441 * {@code "#"} (for example, {@code "com.oracle.jdk.VMInfo#period"}). The value 442 * is a textual representation of the settings value (for example, 443 * {@code "60 s"}). 444 * 445 * @param recordingId the ID of the recordings to get settings for 446 * 447 * @return a map that describes the recording settings, not {@code null} 448 * 449 * @throws IllegalArgumentException if no recording with the specified ID exists 450 * @throws java.lang.SecurityException if a security manager exists and the 451 * caller does not have {@code ManagementPermission("monitor")} 452 */ 453 Map<String, String> getRecordingSettings(long recordingId) throws IllegalArgumentException; 454 455 /** 456 * Sets a configuration as a string representation for the recording with the 457 * specified ID. 458 * 459 * @param recordingId ID of the recording 460 * @param contents a string representation of the configuration file to use, 461 * not {@code null} 462 * @throws IllegalArgumentException if no recording with the 463 * specified ID exists or if the configuration could not be parsed. 464 * @throws java.lang.SecurityException if a security manager exists and the 465 * caller does not have {@code ManagementPermission("control")} 466 * 467 * @see Configuration#getContents() 468 */ 469 void setConfiguration(long recordingId, String contents) throws IllegalArgumentException; 470 471 /** 472 * Sets a predefined configuration for the recording with the specified ID. 473 * 474 * @param recordingId ID of the recording to set the configuration for 475 * @param configurationName the name of the configuration (for example, 476 * {@code "profile"} or {@code "default"}), not {@code null} 477 * @throws IllegalArgumentException if no recording with the 478 * specified ID exists 479 * @throws java.lang.SecurityException if a security manager exists and the 480 * caller does not have {@code ManagementPermission("control")} 481 * 482 * @see #getConfigurations() 483 */ 484 void setPredefinedConfiguration(long recordingId, String configurationName) throws IllegalArgumentException; 485 486 /** 487 * Sets and replaces all previous settings for the specified recording. 488 * <p> 489 * A setting consists of a name/value pair, where <em>name</em> specifies the 490 * event and setting to configure, and the <em>value</em> specifies what to set 491 * it to. 492 * <p> 493 * The name can be formed in the following ways: 494 * <p> 495 * {@code 496 * <event-name> + "#" + <setting-name> 497 * } 498 * <p> 499 * or 500 * <p> 501 * {@code 502 * <event-id> + "#" + <setting-name> 503 * } 504 * <p> 505 * For example, to set the sample interval of the CPU Load event to once every 506 * second, use the name {@code "com.oracle.jdk.CPULoad#period"} and the value 507 * {@code "1 s"}. If multiple events use the same name, for example if an event 508 * class is loaded in multiple class loaders, and differentiation is needed 509 * between them, then the name is {@code "56#period"}. The ID for an event is 510 * obtained by invoking {@link jdk.jfr.EventType#getId()} method and is valid 511 * for the Java Virtual Machine (JVM) instance that the event is registered in. 512 * <p> 513 * A list of available event names is retrieved by invoking 514 * {@link jdk.jfr.FlightRecorder#getEventTypes()} and 515 * {@link jdk.jfr.EventType#getName()}. A list of available settings for an 516 * event type is obtained by invoking 517 * {@link jdk.jfr.EventType#getSettingDescriptors()} and 518 * {@link jdk.jfr.ValueDescriptor#getName()}. 519 * <p> 520 * 521 * @param recordingId ID of the recording 522 * 523 * @param settings name value map of the settings to set, not {@code null} 524 * 525 * @throws IllegalArgumentException if no recording with the specified ID exists 526 * @throws java.lang.SecurityException if a security manager exists and the 527 * caller does not have {@code ManagementPermission("control")} 528 * 529 * @see Recording#getId() 530 */ 531 void setRecordingSettings(long recordingId, Map<String, String> settings) throws IllegalArgumentException; 532 533 /** 534 * Configures the recording options (for example, destination file and time span 535 * to keep data). 536 * <p> 537 * See {@link FlightRecorderMXBean} for a description of the options and values 538 * that can be used. Setting a value to {@code null} restores the value to the 539 * default value. 540 * 541 * @param recordingId the ID of the recording to set options for 542 * 543 * @param options name/value map of the settings to set, not {@code null} 544 * 545 * @throws IllegalArgumentException if no recording with the specified ID exists 546 * @throws java.lang.SecurityException if a security manager exists, and the 547 * caller does not have {@code ManagementPermission("control")} or an 548 * option contains a file that the caller does not have permission to 549 * operate on. 550 * @see Recording#getId() 551 */ 552 void setRecordingOptions(long recordingId, Map<String, String> options) throws IllegalArgumentException; 553 554 /** 555 * Returns the list of the available recordings, not necessarily running. 556 * <p> 557 * <b>MBeanServer access</b>:<br> 558 * The mapped type of {@code RecordingInfo} is {@code CompositeData} with 559 * attributes as specified in the {@link RecordingInfo#from 560 * RecordingInfo.from} method. 561 * 562 * @return list of recordings, not {@code null} 563 * 564 * @throws java.lang.SecurityException if a security manager exists and the 565 * caller does not have {@code ManagementPermission("monitor")} 566 * 567 * @see RecordingInfo 568 * @see Recording 569 */ 570 List<RecordingInfo> getRecordings(); 571 572 /** 573 * Returns the list of predefined configurations for this Java Virtual Machine (JVM). 574 * <p> 575 * <b>MBeanServer access</b>:<br> 576 * The mapped type of {@code ConfigurationInfo} is {@code CompositeData} 577 * with attributes as specified in the {@link ConfigurationInfo#from 578 * ConfigurationInfo.from} method. 579 * 580 * @return the list of predefined configurations, not {@code null} 581 * 582 * @throws java.lang.SecurityException if a security manager exists and the 583 * caller does not have {@code ManagementPermission("monitor")} 584 * 585 * @see ConfigurationInfo 586 * @see Configuration 587 */ 588 List<ConfigurationInfo> getConfigurations(); 589 590 /** 591 * Returns the list of currently registered event typess. 592 * <p> 593 * <b>MBeanServer access</b>:<br> 594 * The mapped type of {@code EventTypeInfo} is {@code CompositeData} with 595 * attributes as specified in the {@link EventTypeInfo#from 596 * EventTypeInfo.from} method. 597 * 598 * @return the list of registered event types, not {@code null} 599 * 600 * @throws java.lang.SecurityException if a security manager exists and the 601 * caller does not have {@code ManagementPermission("monitor")} 602 * 603 * @see EventTypeInfo 604 * @see EventType 605 */ 606 List<EventTypeInfo> getEventTypes(); 607 608 /** 609 * Writes recording data to the specified file. 610 * <p> 611 * If this method is invoked remotely from another process, the data is written 612 * to a file named {@code outputFile} on the machine where the target Java 613 * Virtual Machine (JVM) is running. If the file location is a relative path, it 614 * is relative to the working directory where the target JVM was started. 615 * 616 * @param recordingId the ID of the recording to dump data for 617 * 618 * @param outputFile the system-dependent file name where data is written, not 619 * {@code null} 620 * 621 * @throws IOException if the recording can't be dumped due to an I/O error (for 622 * example, an invalid path)s 623 * 624 * @throws IllegalArgumentException if a recording with the specified ID doesn't 625 * exist 626 * 627 * @throws IllegalStateException if the recording is not yet started or if it is 628 * already closed 629 * 630 * @throws SecurityException if a security manager exists and its 631 * {@code SecurityManager.checkWrite(java.lang.String)} method denies 632 * write access to the named file or the caller does not have 633 * {@code ManagmentPermission("control")} 634 * 635 * @see java.nio.file.Path#toString() 636 * @see Recording#dump(java.nio.file.Path) 637 */ 638 void copyTo(long recordingId, String outputFile) throws IOException, SecurityException; 639 }