1 /* 2 * Copyright (c) 2016, 2020, 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: 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} class documentation for configuration information. 59 * 60 * <h2>Recording options</h2> 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 JVM is running. If destination is a relative path, it 134 * is relative to the working directory where the target JVM 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 ID that can be used to start, stop, close and 183 * configure the recording 184 * 185 * @throws IllegalStateException if Flight Recorder can't be created (for 186 * example, if the Java Virtual Machine (JVM) lacks Flight Recorder 187 * support, or if the file repository can't be created or accessed) 188 * 189 * @throws java.lang.SecurityException if a security manager exists and the 190 * caller does not have {@code ManagementPermission("control")} 191 * 192 * @see Recording 193 */ newRecording()194 long newRecording() throws IllegalStateException, SecurityException; 195 196 /** 197 * Creates a snapshot recording of all available recorded data. 198 * <p> 199 * A snapshot is a synthesized recording in a stopped state. If no data is 200 * available, a recording with size {@code 0} is returned. 201 * <p> 202 * A snapshot provides stable access to data for later operations (for example, 203 * operations to change the time interval or to reduce the data size). 204 * <p> 205 * The caller must close the recording when access to the data is no longer 206 * needed. 207 * 208 * @return a unique ID that can be used for reading recording data 209 * 210 * @throws java.lang.SecurityException if a security manager exists and the 211 * caller does not have {@code ManagementPermission("control")} 212 * 213 * @see Recording 214 */ takeSnapshot()215 public long takeSnapshot(); 216 217 /** 218 * Creates a copy of an existing recording, useful for extracting parts of a 219 * recording. 220 * <p> 221 * The cloned recording contains the same recording data as the 222 * original, but it has a new ID and a name prefixed with 223 * {@code "Clone of recording"}. If the original recording is running, then 224 * the clone is also running. 225 * 226 * @param recordingId the recording ID of the recording to create a clone 227 * from 228 * 229 * @param stop if the newly created clone is stopped before 230 * returning. 231 * 232 * @return a unique ID that can be used to start, stop, 233 * close and configure the recording 234 * 235 * @throws IllegalArgumentException if a recording with the specified ID 236 * doesn't exist 237 * 238 * @throws java.lang.SecurityException if a security manager exists and the 239 * caller does not have {@code ManagementPermission("control")} 240 * 241 * @see Recording 242 */ cloneRecording(long recordingId, boolean stop)243 long cloneRecording(long recordingId, boolean stop) throws IllegalArgumentException, SecurityException; 244 245 /** 246 * Starts the recording with the specified ID. 247 * <p> 248 * A recording that is stopped can't be restarted. 249 * 250 * @param recordingId ID of the recording to start 251 * 252 * @throws IllegalArgumentException if a recording with the specified ID 253 * doesn't exist 254 * 255 * @throws java.lang.SecurityException if a security manager exists and the 256 * caller does not have {@code ManagementPermission("control")} 257 * 258 * @see Recording 259 */ startRecording(long recordingId)260 void startRecording(long recordingId) throws IllegalStateException, SecurityException; 261 262 /** 263 * Stops the running recording with the specified ID. 264 * 265 * @param recordingId the ID of the recording to stop 266 * 267 * @return {@code true} if the recording is stopped, {@code false} 268 * otherwise 269 * 270 * @throws IllegalArgumentException if a recording with the specified ID 271 * doesn't exist 272 * @throws IllegalStateException if the recording is not running 273 * @throws java.lang.SecurityException if a security manager exists and the 274 * caller does not have {@code ManagementPermission("control")} 275 * 276 * @see #newRecording() 277 */ stopRecording(long recordingId)278 boolean stopRecording(long recordingId) throws IllegalArgumentException, IllegalStateException, SecurityException; 279 280 /** 281 * Closes the recording with the specified ID and releases any system 282 * resources that are associated with the recording. 283 * <p> 284 * If the recording is already closed, invoking this method has no effect. 285 * 286 * @param recordingId the ID of the recording to close 287 * 288 * @throws IllegalArgumentException if a recording with the specified ID 289 * doesn't exist 290 * @throws IOException if an I/O error occurs 291 * @throws java.lang.SecurityException if a security manager exists and the 292 * caller does not have {@code ManagementPermission("control")} 293 * 294 * @see #newRecording() 295 */ closeRecording(long recordingId)296 void closeRecording(long recordingId) throws IOException; 297 298 /** 299 * Opens a data stream for the recording with the specified ID, or {@code 0} 300 * to get data irrespective of recording. 301 * <table class="striped"> 302 * <caption>Recording stream options</caption> 303 * <thead> 304 * <tr> 305 * <th scope="col">Name</th> 306 * <th scope="col">Descripion</th> 307 * <th scope="col">Default value</th> 308 * <th scope="col">Format</th> 309 * <th scope="col">Example values</th> 310 * </tr> 311 * </thead> 312 * <tbody> 313 * <tr> 314 * <th scope="row">{@code startTime}</th> 315 * <td>Specifies the point in time to start a recording stream. Due to 316 * how data is stored, some events that start or end prior to the 317 * start time may be included.</td> 318 * <td>{@code Instant.MIN_VALUE.toString()}</td> 319 * <td>ISO-8601. See {@link Instant#toString}<br> 320 * or milliseconds since epoch</td> 321 * <td>{@code "2015-11-03T00:00"},<br> 322 * {@code "1446508800000"}</td> 323 * </tr> 324 * <tr> 325 * <th scope="row">{@code endTime}</th> 326 * <td>Specifies the point in time to end a recording stream. Due to how 327 * data is stored, some events that start or end after the end time may 328 * be included.</td> 329 * <td>{@code Instant.MAX_VALUE.toString()}</td> 330 * <td>ISO-8601. See {@link Instant#toString} <br> 331 * or milliseconds since epoch</td> 332 * <td>{@code "2015-11-03T01:00"}, <br> 333 * {@code "1446512400000"}</td> 334 * </tr> 335 * 336 * <tr> 337 * <th scope="row">{@code blockSize}</th> 338 * <td>Specifies the maximum number of bytes to read with a call to {@code readStream} 339 * </td> 340 * <td>{@code "50000"}</td> 341 * <td>A positive {@code long} value. <br> 342 * <br> 343 * Setting {@code blockSize} to a very high value may result in 344 * {@link OutOfMemoryError} or an {@link IllegalArgumentException}, if the 345 * Java Virtual Machine (JVM) deems the value too large to handle.</td> 346 * <td>{@code "50000"},<br> 347 * {@code "1000000"},<br> 348 * </tr> 349 * <tr> 350 * <th scope="row">{@code streamVersion}</th> 351 * <td>Specifies format to use when reading data from a running recording 352 * </td> 353 * <td>{@code "1.0"}</td> 354 * <td>A version number with a major and minor.<br> 355 * <br> 356 * To be able to read from a running recording the value must be set</td> 357 * <td>{@code "1.0"} 358 * </tr> 359 * </tbody> 360 * </table> 361 * If an option is omitted from the map the default value is used. 362 * <p> 363 * The recording with the specified ID must be stopped before a stream can 364 * be opened, unless the option {@code "streamVersion"} is specified. 365 * 366 * @param recordingId ID of the recording to open the stream for 367 * 368 * @param streamOptions a map that contains the options that controls the amount of data 369 * and how it is read, or {@code null} to get all data for the 370 * recording with the default block size 371 * 372 * @return a unique ID for the stream. 373 * 374 * @throws IllegalArgumentException if a recording with the iD doesn't 375 * exist, or if {@code options} contains invalid values 376 * 377 * @throws IOException if the recording is closed, an I/O error occurs, or 378 * no data is available for the specified recording or 379 * interval 380 * 381 * @throws java.lang.SecurityException if a security manager exists and the 382 * caller does not have {@code ManagementPermission("control")} 383 */ openStream(long recordingId, Map<String, String> streamOptions)384 long openStream(long recordingId, Map<String, String> streamOptions) throws IOException; 385 386 /** 387 * Closes the recording stream with the specified ID and releases any system 388 * resources that are associated with the stream. 389 * <p> 390 * If the stream is already closed, invoking this method has no effect. 391 * 392 * @param streamId the ID of the stream 393 * 394 * @throws IllegalArgumentException if a stream with the specified ID doesn't 395 * exist 396 * @throws IOException if an I/O error occurs while trying to close the stream 397 * @throws java.lang.SecurityException if a security manager exists and the 398 * caller does not have {@code ManagementPermission("control")} 399 * 400 * @see #openStream(long, Map) 401 */ closeStream(long streamId)402 void closeStream(long streamId) throws IOException; 403 404 /** 405 * Reads a portion of data from the stream with the specified ID, or returns 406 * {@code null} if no more data is available. 407 * <p> 408 * To read all data for a recording, invoke this method repeatedly until 409 * {@code null} is returned. 410 * 411 * @param streamId the ID of the stream 412 * 413 * @return byte array that contains recording data, or {@code null} when no more 414 * data is available 415 * @throws IOException if the stream is closed, or an I/O error occurred while 416 * trying to read the stream 417 * @throws IllegalArgumentException if no recording with the stream ID exists 418 * @throws java.lang.SecurityException if a security manager exists and the 419 * caller does not have {@code ManagementPermission("monitor")} 420 */ readStream(long streamId)421 byte[] readStream(long streamId) throws IOException; 422 423 /** 424 * Returns a map that contains the options for the recording with the 425 * specified ID (for example, the destination file or time span to keep 426 * recorded data). 427 * <p> 428 * See {@link FlightRecorderMXBean} for available option names. 429 * 430 * @param recordingId the ID of the recording to get options for 431 * 432 * @return a map describing the recording options, not {@code null} 433 * 434 * @throws IllegalArgumentException if no recording with the 435 * specified ID exists 436 * @throws java.lang.SecurityException if a security manager exists and the 437 * caller does not have {@code ManagementPermission("monitor")} 438 * 439 */ getRecordingOptions(long recordingId)440 Map<String, String> getRecordingOptions(long recordingId) throws IllegalArgumentException; 441 442 /** 443 * Returns a {@code Map} that contains the settings for the recording with the specified ID, 444 * (for example, the event thresholds) 445 * <p> 446 * If multiple recordings are running at the same time, more data could be 447 * recorded than what is specified in the {@code Map} object. 448 * <p> 449 * The name in the {@code Map} is the event name and the setting name separated by 450 * {@code "#"} (for example, {@code "jdk.VMInfo#period"}). The value 451 * is a textual representation of the settings value (for example, 452 * {@code "60 s"}). 453 * 454 * @param recordingId the ID of the recordings to get settings for 455 * 456 * @return a map that describes the recording settings, not {@code null} 457 * 458 * @throws IllegalArgumentException if no recording with the specified ID exists 459 * @throws java.lang.SecurityException if a security manager exists and the 460 * caller does not have {@code ManagementPermission("monitor")} 461 */ getRecordingSettings(long recordingId)462 Map<String, String> getRecordingSettings(long recordingId) throws IllegalArgumentException; 463 464 /** 465 * Sets a configuration as a string representation for the recording with the 466 * specified ID. 467 * 468 * @param recordingId ID of the recording 469 * @param contents a string representation of the configuration file to use, 470 * not {@code null} 471 * @throws IllegalArgumentException if no recording with the 472 * specified ID exists or if the configuration could not be parsed. 473 * @throws java.lang.SecurityException if a security manager exists and the 474 * caller does not have {@code ManagementPermission("control")} 475 * 476 * @see Configuration#getContents() 477 */ setConfiguration(long recordingId, String contents)478 void setConfiguration(long recordingId, String contents) throws IllegalArgumentException; 479 480 /** 481 * Sets a predefined configuration for the recording with the specified ID. 482 * 483 * @param recordingId ID of the recording to set the configuration for 484 * @param configurationName the name of the configuration (for example, 485 * {@code "profile"} or {@code "default"}), not {@code null} 486 * @throws IllegalArgumentException if no recording with the 487 * specified ID exists 488 * @throws java.lang.SecurityException if a security manager exists and the 489 * caller does not have {@code ManagementPermission("control")} 490 * 491 * @see #getConfigurations() 492 */ setPredefinedConfiguration(long recordingId, String configurationName)493 void setPredefinedConfiguration(long recordingId, String configurationName) throws IllegalArgumentException; 494 495 /** 496 * Sets and replaces all previous settings for the specified recording. 497 * <p> 498 * A setting consists of a name/value pair, where <em>name</em> specifies the 499 * event and setting to configure, and the <em>value</em> specifies what to set 500 * it to. 501 * <p> 502 * The name can be formed in the following ways: 503 * <p> 504 * {@code 505 * <event-name> + "#" + <setting-name> 506 * } 507 * <p> 508 * or 509 * <p> 510 * {@code 511 * <event-id> + "#" + <setting-name> 512 * } 513 * <p> 514 * For example, to set the sample interval of the CPU Load event to once every 515 * second, use the name {@code "jdk.CPULoad#period"} and the value 516 * {@code "1 s"}. If multiple events use the same name, for example if an event 517 * class is loaded in multiple class loaders, and differentiation is needed 518 * between them, then the name is {@code "56#period"}. The ID for an event is 519 * obtained by invoking {@link jdk.jfr.EventType#getId()} method and is valid 520 * for the Java Virtual Machine (JVM) instance that the event is registered in. 521 * <p> 522 * A list of available event names is retrieved by invoking 523 * {@link jdk.jfr.FlightRecorder#getEventTypes()} and 524 * {@link jdk.jfr.EventType#getName()}. A list of available settings for an 525 * event type is obtained by invoking 526 * {@link jdk.jfr.EventType#getSettingDescriptors()} and 527 * {@link jdk.jfr.ValueDescriptor#getName()}. 528 * 529 * @param recordingId ID of the recording 530 * 531 * @param settings name value map of the settings to set, not {@code null} 532 * 533 * @throws IllegalArgumentException if no recording with the specified ID exists 534 * @throws java.lang.SecurityException if a security manager exists and the 535 * caller does not have {@code ManagementPermission("control")} 536 * 537 * @see Recording#getId() 538 */ setRecordingSettings(long recordingId, Map<String, String> settings)539 void setRecordingSettings(long recordingId, Map<String, String> settings) throws IllegalArgumentException; 540 541 /** 542 * Configures the recording options (for example, destination file and time span 543 * to keep data). 544 * <p> 545 * See {@link FlightRecorderMXBean} for a description of the options and values 546 * that can be used. Setting a value to {@code null} restores the value to the 547 * default value. 548 * 549 * @param recordingId the ID of the recording to set options for 550 * 551 * @param options name/value map of the settings to set, not {@code null} 552 * 553 * @throws IllegalArgumentException if no recording with the specified ID exists 554 * @throws java.lang.SecurityException if a security manager exists, and the 555 * caller does not have {@code ManagementPermission("control")} or an 556 * option contains a file that the caller does not have permission to 557 * operate on. 558 * @see Recording#getId() 559 */ setRecordingOptions(long recordingId, Map<String, String> options)560 void setRecordingOptions(long recordingId, Map<String, String> options) throws IllegalArgumentException; 561 562 /** 563 * Returns the list of the available recordings, not necessarily running. 564 * <p> 565 * <b>MBeanServer access</b>:<br> 566 * The mapped type of {@code RecordingInfo} is {@code CompositeData} with 567 * attributes as specified in the {@link RecordingInfo#from 568 * RecordingInfo.from} method. 569 * 570 * @return list of recordings, not {@code null} 571 * 572 * @throws java.lang.SecurityException if a security manager exists and the 573 * caller does not have {@code ManagementPermission("monitor")} 574 * 575 * @see RecordingInfo 576 * @see Recording 577 */ getRecordings()578 List<RecordingInfo> getRecordings(); 579 580 /** 581 * Returns the list of predefined configurations for this Java Virtual Machine (JVM). 582 * <p> 583 * <b>MBeanServer access</b>:<br> 584 * The mapped type of {@code ConfigurationInfo} is {@code CompositeData} 585 * with attributes as specified in the {@link ConfigurationInfo#from 586 * ConfigurationInfo.from} method. 587 * 588 * @return the list of predefined configurations, not {@code null} 589 * 590 * @throws java.lang.SecurityException if a security manager exists and the 591 * caller does not have {@code ManagementPermission("monitor")} 592 * 593 * @see ConfigurationInfo 594 * @see Configuration 595 */ getConfigurations()596 List<ConfigurationInfo> getConfigurations(); 597 598 /** 599 * Returns the list of currently registered event types. 600 * <p> 601 * <b>MBeanServer access</b>:<br> 602 * The mapped type of {@code EventTypeInfo} is {@code CompositeData} with 603 * attributes as specified in the {@link EventTypeInfo#from 604 * EventTypeInfo.from} method. 605 * 606 * @return the list of registered event types, not {@code null} 607 * 608 * @throws java.lang.SecurityException if a security manager exists and the 609 * caller does not have {@code ManagementPermission("monitor")} 610 * 611 * @see EventTypeInfo 612 * @see EventType 613 */ getEventTypes()614 List<EventTypeInfo> getEventTypes(); 615 616 /** 617 * Writes recording data to the specified file. 618 * <p> 619 * If this method is invoked remotely from another process, the data is written 620 * to a file named {@code outputFile} on the machine where the target Java 621 * Virtual Machine (JVM) is running. If the file location is a relative path, it 622 * is relative to the working directory where the target JVM was started. 623 * 624 * @param recordingId the ID of the recording to dump data for 625 * 626 * @param outputFile the system-dependent file name where data is written, not 627 * {@code null} 628 * 629 * @throws IOException if the recording can't be dumped due to an I/O error (for 630 * example, an invalid path) 631 * 632 * @throws IllegalArgumentException if a recording with the specified ID doesn't 633 * exist 634 * 635 * @throws IllegalStateException if the recording is not yet started or if it is 636 * already closed 637 * 638 * @throws SecurityException if a security manager exists and its 639 * {@code SecurityManager.checkWrite(java.lang.String)} method denies 640 * write access to the named file or the caller does not have 641 * {@code ManagmentPermission("control")} 642 * 643 * @see java.nio.file.Path#toString() 644 * @see Recording#dump(java.nio.file.Path) 645 */ copyTo(long recordingId, String outputFile)646 void copyTo(long recordingId, String outputFile) throws IOException, SecurityException; 647 } 648