feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
241
jdkSrc/jdk8/jdk/management/jfr/ConfigurationInfo.java
Normal file
241
jdkSrc/jdk8/jdk/management/jfr/ConfigurationInfo.java
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.TabularData;
|
||||
|
||||
import jdk.jfr.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
* Management representation of a {@code Configuration}.
|
||||
*
|
||||
* @see Configuration
|
||||
*
|
||||
* @since 8
|
||||
*/
|
||||
public final class ConfigurationInfo {
|
||||
private final Map<String, String> settings;
|
||||
private final String name;
|
||||
private final String label;
|
||||
private final String description;
|
||||
private final String provider;
|
||||
private final String contents;
|
||||
|
||||
ConfigurationInfo(Configuration config) {
|
||||
this.settings = config.getSettings();
|
||||
this.name = config.getName();
|
||||
this.label = config.getLabel();
|
||||
this.description = config.getDescription();
|
||||
this.provider = config.getProvider();
|
||||
this.contents = config.getContents();
|
||||
}
|
||||
|
||||
private ConfigurationInfo(CompositeData cd) {
|
||||
this.settings = createMap(cd.get("settings"));
|
||||
this.name = (String) cd.get("name");
|
||||
this.label = (String) cd.get("label");
|
||||
this.description = (String) cd.get("description");
|
||||
this.provider = (String) cd.get("provider");
|
||||
this.contents = (String) cd.get("contents");
|
||||
}
|
||||
|
||||
private static Map<String, String> createMap(Object o) {
|
||||
if (o instanceof TabularData) {
|
||||
TabularData td = (TabularData) o;
|
||||
Collection<?> values = td.values();
|
||||
Map<String, String> map = new HashMap<>(values.size());
|
||||
for (Object value : td.values()) {
|
||||
if (value instanceof CompositeData) {
|
||||
CompositeData cdRow = (CompositeData) value;
|
||||
Object k = cdRow.get("key");
|
||||
Object v = cdRow.get("value");
|
||||
if (k instanceof String && v instanceof String) {
|
||||
map.put((String) k, (String) v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableMap(map);
|
||||
}
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the provider of the configuration associated with this
|
||||
* {@code ConfigurationInfo} (for example, {@code "OpenJDK"}).
|
||||
*
|
||||
* @return the provider, or {@code null} if doesn't exist
|
||||
*
|
||||
* @see Configuration#getProvider()
|
||||
*/
|
||||
public String getProvider() {
|
||||
return provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textual representation of the configuration associated with
|
||||
* this {@code ConfigurationInfo}, typically the contents of the
|
||||
* configuration file that was used to create the configuration.
|
||||
*
|
||||
* @return contents, or {@code null} if doesn't exist
|
||||
*
|
||||
* @see Configuration#getContents()
|
||||
*/
|
||||
public String getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings for the configuration associated with this
|
||||
* {@code ConfigurationInfo}.
|
||||
*
|
||||
* @return a {@code Map} with settings, not {@code null}
|
||||
*
|
||||
* @see Configuration#getSettings()
|
||||
*/
|
||||
public Map<String, String> getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human-readable name (for example, {@code "Continuous"} or {@code "Profiling"}) for
|
||||
* the configuration associated with this {@code ConfigurationInfo}
|
||||
*
|
||||
* @return the label, or {@code null} if doesn't exist
|
||||
*
|
||||
* @see Configuration#getLabel()
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the configuration associated with this
|
||||
* {@code ConfigurationInfo} (for example, {@code "default"}).
|
||||
*
|
||||
* @return the name, or {@code null} if doesn't exist
|
||||
*
|
||||
* @see Configuration#getLabel()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short sentence that describes the configuration associated with
|
||||
* this {@code ConfigurationInfo} (for example, {@code "Low
|
||||
* overhead configuration safe for continuous use in production
|
||||
* environments"}.
|
||||
*
|
||||
* @return the description, or {@code null} if doesn't exist
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code ConfigurationInfo} object represented by the specified
|
||||
* {@code CompositeData}.
|
||||
* <p>
|
||||
* The following table shows the required attributes that the specified {@code CompositeData} must contain.
|
||||
* <blockquote>
|
||||
* <table class="striped">
|
||||
* <caption>Required names and types for CompositeData</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col" style="text-align:left">Name</th>
|
||||
* <th scope="col" style="text-align:left">Type</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th scope="row">name</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">label</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">description</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">provider</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">contents</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <th scope="row">settings</th>
|
||||
* <td>{@code javax.management.openmbean.TabularData} with a
|
||||
* {@code TabularType} with the keys {@code "key"} and {@code "value"}, both
|
||||
* of the {@code String} type</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* @param cd {@code CompositeData} representing a {@code ConfigurationInfo}
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code cd} does not represent a
|
||||
* {@code ConfigurationInfo} with the required attributes
|
||||
*
|
||||
* @return a {@code ConfigurationInfo} object represented by {@code cd} if
|
||||
* {@code cd} is not {@code null}, {@code null} otherwise
|
||||
*/
|
||||
public static ConfigurationInfo from(CompositeData cd) {
|
||||
if (cd == null) {
|
||||
return null;
|
||||
}
|
||||
return new ConfigurationInfo(cd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of the configuration that is associated with this
|
||||
* {@code ConfigurationInfo}.
|
||||
*
|
||||
* @return the description of the configuration, not {@code null}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
Stringifier s = new Stringifier();
|
||||
s.add("name", name);
|
||||
s.add("label", label);
|
||||
s.add("description", description);
|
||||
s.add("provider", provider);
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
262
jdkSrc/jdk8/jdk/management/jfr/EventTypeInfo.java
Normal file
262
jdkSrc/jdk8/jdk/management/jfr/EventTypeInfo.java
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
import javax.management.openmbean.CompositeData;
|
||||
|
||||
import jdk.jfr.Category;
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.SettingDescriptor;
|
||||
|
||||
/**
|
||||
* Management representation of an {@code EventType}.
|
||||
*
|
||||
* @see EventType
|
||||
*
|
||||
* @since 8
|
||||
*/
|
||||
public final class EventTypeInfo {
|
||||
private final List<SettingDescriptorInfo> settings;
|
||||
private final long id;
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final String label;
|
||||
private final List<String> categoryNames;
|
||||
|
||||
// package private
|
||||
EventTypeInfo(EventType eventType) {
|
||||
this.settings = creatingSettingDescriptorInfos(eventType);
|
||||
this.id = eventType.getId();
|
||||
this.name = eventType.getName();
|
||||
this.label = eventType.getLabel();
|
||||
this.description = eventType.getDescription();
|
||||
this.categoryNames = eventType.getCategoryNames();
|
||||
}
|
||||
|
||||
private EventTypeInfo(CompositeData cd) {
|
||||
this.settings = createSettings(cd.get("settings"));
|
||||
this.id = (long) cd.get("id");
|
||||
this.name = (String) cd.get("name");
|
||||
this.label = (String) cd.get("label");
|
||||
this.description = (String) cd.get("description");
|
||||
this.categoryNames = createCategoryNames((Object[]) cd.get("category"));
|
||||
}
|
||||
|
||||
private static List<String> createCategoryNames(Object[] array) {
|
||||
List<String> list = new ArrayList<>(array.length);
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
list.add((String) array[i]);
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
|
||||
private static List<SettingDescriptorInfo> creatingSettingDescriptorInfos(EventType eventType) {
|
||||
List<SettingDescriptor> settings = eventType.getSettingDescriptors();
|
||||
List<SettingDescriptorInfo> settingDescriptorInfos = new ArrayList<>(settings.size());
|
||||
for (SettingDescriptor s : settings) {
|
||||
settingDescriptorInfos.add(new SettingDescriptorInfo(s));
|
||||
}
|
||||
return Collections.unmodifiableList(settingDescriptorInfos);
|
||||
}
|
||||
|
||||
private static List<SettingDescriptorInfo> createSettings(Object settings) {
|
||||
if (settings != null && settings.getClass().isArray()) {
|
||||
Object[] settingsArray = (Object[]) settings;
|
||||
List<SettingDescriptorInfo> list = new ArrayList<>(settingsArray.length);
|
||||
for (Object cd : settingsArray) {
|
||||
if (cd instanceof CompositeData) {
|
||||
list.add(SettingDescriptorInfo.from((CompositeData) cd));
|
||||
}
|
||||
}
|
||||
return Collections.unmodifiableList(list);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label, a human-readable name, associated with the event type
|
||||
* for this {@code EventTypeInfo} (for example, {@code "Garbage Collection"}).
|
||||
*
|
||||
* @return the label, or {@code null} if a label is not set
|
||||
*
|
||||
* @see EventType#getLabel()
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Returns the list of human-readable names that makes up the category for this
|
||||
* {@code EventTypeInfo} (for example, {@code "Java Virtual Machine"} or {@code "Garbage Collector"}).
|
||||
*
|
||||
* @return an immutable list of category names, or a list with the name
|
||||
* {@code "Uncategorized"} if no category has been set
|
||||
*
|
||||
* @see EventType#getCategoryNames()
|
||||
* @see Category
|
||||
*/
|
||||
public List<String> getCategoryNames() {
|
||||
return categoryNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique ID for the event type associated with this
|
||||
* {@code EventTypeInfo}, not guaranteed to be the same for different Java
|
||||
* Virtual Machines (JVMs) instances.
|
||||
*
|
||||
* @return the ID
|
||||
*
|
||||
* @see EventType#getId()
|
||||
*/
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name for the event type associated with this
|
||||
* {@code EventTypeInfo} (for example, {@code "jdk.GarbageCollection"}).
|
||||
*
|
||||
* @return the name, not {@code null}
|
||||
*
|
||||
* @see EventType#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a short sentence or two describing the event type associated with
|
||||
* this {@code EventTypeInfo}, for example
|
||||
* {@code "Garbage collection performed by the JVM""}.
|
||||
*
|
||||
* @return the description, or {@code null} if no description exists
|
||||
*
|
||||
* @see EventType#getDescription()
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns settings for the event type associated with this
|
||||
* {@code EventTypeInfo}.
|
||||
*
|
||||
* @return the settings, not {@code null}
|
||||
*
|
||||
* @see EventType#getSettingDescriptors()
|
||||
*/
|
||||
public List<SettingDescriptorInfo> getSettingDescriptors() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a description of this {@code EventTypeInfo}.
|
||||
*
|
||||
* @return description, not {@code null}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
Stringifier s = new Stringifier();
|
||||
s.add("id", id);
|
||||
s.add("name", name);
|
||||
s.add("label", label);
|
||||
s.add("description", description);
|
||||
StringJoiner sj = new StringJoiner(", ", "{", "}");
|
||||
for (String categoryName : categoryNames) {
|
||||
sj.add(categoryName);
|
||||
}
|
||||
s.add("category", sj.toString());
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code EventType} represented by the specified
|
||||
* {@code CompositeData}
|
||||
* <p>
|
||||
* The supplied {@code CompositeData} must have the following item names and
|
||||
* item types to be valid. <blockquote>
|
||||
* <table class="striped">
|
||||
* <caption>The name and type the specified CompositeData must contain</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col" style="text-align:left">Name</th>
|
||||
* <th scope="col" style="text-align:left">Type</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th scope="row">id</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">name</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">label</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">description</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">category</th>
|
||||
* <td><code>ArrayType(1, SimpleType.STRING)</code></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">settings</th>
|
||||
* <td>{@code javax.management.openmbean.CompositeData[]} whose element type
|
||||
* is the mapped type for {@link SettingDescriptorInfo} as specified in the
|
||||
* {@link SettingDescriptorInfo#from} method.</td>
|
||||
*
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* @param cd {@code CompositeData} representing the {@code EventTypeInfo} to
|
||||
* return
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code cd} does not represent a valid
|
||||
* {@code EventTypeInfo}
|
||||
*
|
||||
* @return an {@code EventTypeInfo}, or {@code null} if {@code cd} is
|
||||
* {@code null}
|
||||
*/
|
||||
public static EventTypeInfo from(CompositeData cd) {
|
||||
if (cd == null) {
|
||||
return null;
|
||||
}
|
||||
return new EventTypeInfo(cd);
|
||||
}
|
||||
}
|
||||
639
jdkSrc/jdk8/jdk/management/jfr/FlightRecorderMXBean.java
Normal file
639
jdkSrc/jdk8/jdk/management/jfr/FlightRecorderMXBean.java
Normal file
@@ -0,0 +1,639 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.management.PlatformManagedObject;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.jfr.Configuration;
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.Recording;
|
||||
|
||||
/**
|
||||
* Management interface for controlling Flight Recorder.
|
||||
* <p>
|
||||
* The object name for identifying the MXBean in the platform MBean
|
||||
* server is: <blockquote> {@code jdk.management.jfr:type=FlightRecorder} </blockquote>
|
||||
* <p>
|
||||
* Flight Recorder can be configured in the following ways:
|
||||
* <ul>
|
||||
* <li><b>Recording options</b><br>
|
||||
* Specify how long a recording should last, and where and when data
|
||||
* should be dumped.</li>
|
||||
* <li><b>Settings</b><br>
|
||||
* Specify which events should be enabled and what kind information each
|
||||
* event should capture.</li>
|
||||
* <li><b>Configurations</b><br>
|
||||
* Predefined sets of settings, typically derived from a settings file,
|
||||
* that specify the configuration of multiple events simultaneously.</li>
|
||||
* </ul>
|
||||
* <p>
|
||||
* See the package {@code jdk.jfr} documentation for descriptions of the settings
|
||||
* syntax and the {@link ConfigurationInfo} class documentation for configuration information.
|
||||
*
|
||||
* <h3>Recording options</h3>
|
||||
* <p>
|
||||
* The following table shows the options names to use with {@link #setRecordingOptions(long, Map)}
|
||||
* and {@link #getRecordingOptions(long)}.
|
||||
*
|
||||
* <table class="striped">
|
||||
* <caption>Recording options</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col">Name</th>
|
||||
* <th scope="col">Descripion</th>
|
||||
* <th scope="col">Default value</th>
|
||||
* <th scope="col">Format</th>
|
||||
* <th scope="col">Example values</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th scope="row">{@code name}</th>
|
||||
* <td>Sets a human-readable recording name</td>
|
||||
* <td>String representation of the recording id</td>
|
||||
* <td>{@code String}</td>
|
||||
* <td>{@code "My Recording"}, <br>
|
||||
* {@code "profiling"}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">{@code maxAge}</th>
|
||||
* <td>Specify the length of time that the data is kept in the disk repository until the
|
||||
* oldest data may be deleted. Only works if {@code disk=true}, otherwise
|
||||
* this parameter is ignored.</td>
|
||||
* <td>{@code "0"} (no limit)</td>
|
||||
* <td>{@code "0"} if no limit is imposed, otherwise a string
|
||||
* representation of a positive {@code Long} value followed by an empty space
|
||||
* and one of the following units,<br>
|
||||
* <br>
|
||||
* {@code "ns"} (nanoseconds)<br>
|
||||
* {@code "us"} (microseconds)<br>
|
||||
* {@code "ms"} (milliseconds)<br>
|
||||
* {@code "s"} (seconds)<br>
|
||||
* {@code "m"} (minutes)<br>
|
||||
* {@code "h"} (hours)<br>
|
||||
* {@code "d"} (days)<br>
|
||||
* </td>
|
||||
* <td>{@code "2 h"},<br>
|
||||
* {@code "24 h"},<br>
|
||||
* {@code "2 d"},<br>
|
||||
* {@code "0"}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">{@code maxSize}</th>
|
||||
* <td>Specifies the size, measured in bytes, at which data is kept in disk
|
||||
* repository. Only works if
|
||||
* {@code disk=true}, otherwise this parameter is ignored.</td>
|
||||
* <td>{@code "0"} (no limit)</td>
|
||||
* <td>String representation of a {@code Long} value, must be positive</td>
|
||||
* <td>{@code "0"}, <br>
|
||||
* {@code "1000000000"}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">{@code dumpOnExit}</th>
|
||||
* <td>Dumps recording data to disk on Java Virtual Machine (JVM) exit</td>
|
||||
* <td>{@code "false"}</td>
|
||||
* <td>String representation of a {@code Boolean} value, {@code "true"} or
|
||||
* {@code "false"}</td>
|
||||
* <td>{@code "true"},<br>
|
||||
* {@code "false"}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">{@code destination}</th>
|
||||
* <td>Specifies the path where recording data is written when the recording stops.</td>
|
||||
* <td>{@code "false"}</td>
|
||||
* <td>See {@code Paths#getPath} for format. <br>
|
||||
* If this method is invoked from another process, the data is written on the
|
||||
* machine where the target JVM is running. If destination is a relative path, it
|
||||
* is relative to the working directory where the target JVM was started.}</td>
|
||||
* <td>{@code "c:\recording\recotding.jfr"},<br>
|
||||
* {@code "/recordings/recording.jfr"}, {@code "recording.jfr"}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">{@code disk}</th>
|
||||
* <td>Stores recorded data as it is recorded</td>
|
||||
* <td><code>"false"</code></td>
|
||||
* <td>String representation of a {@code Boolean} value, {@code "true"} or
|
||||
* {@code "false"}</td>
|
||||
* <td>{@code "true"},<br>
|
||||
* {@code "false"}</td>
|
||||
* <tr>
|
||||
* <th scope="row">{@code duration}</th>
|
||||
* <td>Sets how long the recording should be running</td>
|
||||
* <td>{@code "0"} (no limit, continuous)</td>
|
||||
* <td>{@code "0"} if no limit should be imposed, otherwise a string
|
||||
* representation of a positive {@code Long} followed by an empty space and one
|
||||
* of the following units:<br>
|
||||
* <br>
|
||||
* {@code "ns"} (nanoseconds)<br>
|
||||
* {@code "us"} (microseconds)<br>
|
||||
* {@code "ms"} (milliseconds)<br>
|
||||
* {@code "s"} (seconds)<br>
|
||||
* {@code "m"} (minutes)<br>
|
||||
* {@code "h"} (hours)<br>
|
||||
* {@code "d"} (days)<br>
|
||||
* </td>
|
||||
* <td>{@code "60 s"},<br>
|
||||
* {@code "10 m"},<br>
|
||||
* {@code "4 h"},<br>
|
||||
* {@code "0"}</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
*
|
||||
* @since 8
|
||||
*/
|
||||
public interface FlightRecorderMXBean extends PlatformManagedObject {
|
||||
/**
|
||||
* String representation of the {@code ObjectName} for the
|
||||
* {@code FlightRecorderMXBean}.
|
||||
*/
|
||||
public static final String MXBEAN_NAME = "jdk.management.jfr:type=FlightRecorder";
|
||||
|
||||
/**
|
||||
* Creates a recording, but doesn't start it.
|
||||
*
|
||||
* @return a unique ID that can be used to start, stop, close and
|
||||
* configure the recording
|
||||
*
|
||||
* @throws IllegalStateException if Flight Recorder can't be created (for
|
||||
* example, if the Java Virtual Machine (JVM) lacks Flight Recorder
|
||||
* support, or if the file repository can't be created or accessed)
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see Recording
|
||||
*/
|
||||
long newRecording() throws IllegalStateException, SecurityException;
|
||||
|
||||
/**
|
||||
* Creates a snapshot recording of all available recorded data.
|
||||
* <p>
|
||||
* A snapshot is a synthesized recording in a stopped state. If no data is
|
||||
* available, a recording with size {@code 0} is returned.
|
||||
* <p>
|
||||
* A snapshot provides stable access to data for later operations (for example,
|
||||
* operations to change the time interval or to reduce the data size).
|
||||
* <p>
|
||||
* The caller must close the recording when access to the data is no longer
|
||||
* needed.
|
||||
*
|
||||
* @return a snapshot of all available recording data, not {@code null}
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @return a unique ID that can be used for reading recording data.
|
||||
*
|
||||
* @see Recording
|
||||
*/
|
||||
public long takeSnapshot();
|
||||
|
||||
/**
|
||||
* Creates a copy of an existing recording, useful for extracting parts of a
|
||||
* recording.
|
||||
* <p>
|
||||
* The cloned recording contains the same recording data as the
|
||||
* original, but it has a new ID and a name prefixed with
|
||||
* {@code "Clone of recording"}. If the original recording is running, then
|
||||
* the clone is also running.
|
||||
*
|
||||
* @param recordingId the recording ID of the recording to create a clone
|
||||
* from
|
||||
*
|
||||
* @param stop if the newly created clone is stopped before
|
||||
* returning.
|
||||
*
|
||||
* @return a unique ID that can be used to start, stop,
|
||||
* close and configure the recording
|
||||
*
|
||||
* @throws IllegalArgumentException if a recording with the specified ID
|
||||
* doesn't exist
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see Recording
|
||||
*/
|
||||
long cloneRecording(long recordingId, boolean stop) throws IllegalArgumentException, SecurityException;
|
||||
|
||||
/**
|
||||
* Starts the recording with the specified ID.
|
||||
* <p>
|
||||
* A recording that is stopped can't be restarted.
|
||||
*
|
||||
* @param recordingId ID of the recording to start
|
||||
*
|
||||
* @throws IllegalArgumentException if a recording with the specified ID
|
||||
* doesn't exist
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see Recording
|
||||
*/
|
||||
void startRecording(long recordingId) throws IllegalStateException, SecurityException;
|
||||
|
||||
/**
|
||||
* Stops the running recording with the specified ID.
|
||||
*
|
||||
* @param recordingId the ID of the recording to stop
|
||||
*
|
||||
* @return {@code true} if the recording is stopped, {@code false}
|
||||
* otherwise
|
||||
*
|
||||
* @throws IllegalArgumentException if a recording with the specified ID
|
||||
* doesn't exist
|
||||
* @throws IllegalStateException if the recording is not running
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see #newRecording()
|
||||
*/
|
||||
boolean stopRecording(long recordingId) throws IllegalArgumentException, IllegalStateException, SecurityException;
|
||||
|
||||
/**
|
||||
* Closes the recording with the specified ID and releases any system
|
||||
* resources that are associated with the recording.
|
||||
* <p>
|
||||
* If the recording is already closed, invoking this method has no effect.
|
||||
*
|
||||
* @param recordingId the ID of the recording to close
|
||||
*
|
||||
* @throws IllegalArgumentException if a recording with the specified ID
|
||||
* doesn't exist
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see #newRecording()
|
||||
*/
|
||||
void closeRecording(long recordingId) throws IOException;
|
||||
|
||||
/**
|
||||
* Opens a data stream for the recording with the specified ID, or {@code 0}
|
||||
* to get data irrespective of recording.
|
||||
* <table class="striped">
|
||||
* <caption>Recording stream options</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col">Name</th>
|
||||
* <th scope="col">Descripion</th>
|
||||
* <th scope="col">Default value</th>
|
||||
* <th scope="col">Format</th>
|
||||
* <th scope="col">Example values</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th scope="row">{@code startTime}</th>
|
||||
* <td>Specifies the point in time to start a recording stream. Due to
|
||||
* how data is stored, some events that start or end prior to the
|
||||
* start time may be included.</td>
|
||||
* <td>{@code Instant.MIN_VALUE.toString()}</td>
|
||||
* <td>ISO-8601. See {@link Instant#toString}<br>
|
||||
* or milliseconds since epoch</td>
|
||||
* <td>{@code "2015-11-03T00:00"},<br>
|
||||
* {@code "1446508800000"}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">{@code endTime}</th>
|
||||
* <td>Specifies the point in time to end a recording stream. Due to how
|
||||
* data is stored, some events that start or end after the end time may
|
||||
* be included.</td>
|
||||
* <td>{@code Instant.MAX_VALUE.toString()}</td>
|
||||
* <td>ISO-8601. See {@link Instant#toString} <br>
|
||||
* or milliseconds since epoch</td>
|
||||
* <td>{@code "2015-11-03T01:00"}, <br>
|
||||
* {@code "1446512400000"}</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <th scope="row">{@code blockSize}</th>
|
||||
* <td>Specifies the maximum number of bytes to read with a call to {@code readStream}
|
||||
* </td>
|
||||
* <td>{@code "50000"}</td>
|
||||
* <td>A positive {@code long} value. <br>
|
||||
* <br>
|
||||
* Setting {@code blockSize} to a very high value may result in
|
||||
* {@link OutOfMemoryError} or an {@link IllegalArgumentException}, if the
|
||||
* Java Virtual Machine (JVM) deems the value too large to handle.</td>
|
||||
* <td>{@code "50000"},<br>
|
||||
* {@code "1000000"},<br>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* If an option is omitted from the map the default value is used.
|
||||
* <p>
|
||||
* The recording with the specified ID must be stopped before a stream can
|
||||
* be opened. This restriction might be lifted in future releases.
|
||||
*
|
||||
* @param recordingId ID of the recording to open the stream for
|
||||
*
|
||||
* @param streamOptions a map that contains the options that controls the amount of data
|
||||
* and how it is read, or {@code null} to get all data for the
|
||||
* recording with the default block size
|
||||
*
|
||||
* @return a unique ID for the stream.
|
||||
*
|
||||
* @throws IllegalArgumentException if a recording with the iD doesn't
|
||||
* exist, or if {@code options} contains invalid values
|
||||
*
|
||||
* @throws IOException if the recording is closed, an I/O error occurs, or
|
||||
* no data is available for the specified recording or
|
||||
* interval
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*/
|
||||
long openStream(long recordingId, Map<String, String> streamOptions) throws IOException;
|
||||
|
||||
/**
|
||||
* Closes the recording stream with the specified ID and releases any system
|
||||
* resources that are associated with the stream.
|
||||
* <p>
|
||||
* If the stream is already closed, invoking this method has no effect.
|
||||
*
|
||||
* @param streamId the ID of the stream
|
||||
*
|
||||
* @throws IllegalArgumentException if a stream with the specified ID doesn't
|
||||
* exist
|
||||
* @throws IOException if an I/O error occurs while trying to close the stream
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see #openStream(long, Map)
|
||||
*/
|
||||
void closeStream(long streamId) throws IOException;
|
||||
|
||||
/**
|
||||
* Reads a portion of data from the stream with the specified ID, or returns
|
||||
* {@code null} if no more data is available.
|
||||
* <p>
|
||||
* To read all data for a recording, invoke this method repeatedly until
|
||||
* {@code null} is returned.
|
||||
*
|
||||
* @param streamId the ID of the stream
|
||||
*
|
||||
* @return byte array that contains recording data, or {@code null} when no more
|
||||
* data is available
|
||||
* @throws IOException if the stream is closed, or an I/O error occurred while
|
||||
* trying to read the stream
|
||||
* @throws IllegalArgumentException if no recording with the stream ID exists
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("monitor")}
|
||||
*/
|
||||
byte[] readStream(long streamId) throws IOException;
|
||||
|
||||
/**
|
||||
* Returns a map that contains the options for the recording with the
|
||||
* specified ID (for example, the destination file or time span to keep
|
||||
* recorded data).
|
||||
* <p>
|
||||
* See {@link FlightRecorderMXBean} for available option names.
|
||||
*
|
||||
* @param recordingId the ID of the recording to get options for
|
||||
*
|
||||
* @return a map describing the recording options, not {@code null}
|
||||
*
|
||||
* @throws IllegalArgumentException if no recording with the
|
||||
* specified ID exists
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("monitor")}
|
||||
*
|
||||
*/
|
||||
Map<String, String> getRecordingOptions(long recordingId) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns a {@code Map} that contains the settings for the recording with the specified ID,
|
||||
* (for example, the event thresholds)
|
||||
* <p>
|
||||
* If multiple recordings are running at the same time, more data could be
|
||||
* recorded than what is specified in the {@code Map} object.
|
||||
* <p>
|
||||
* The name in the {@code Map} is the event name and the setting name separated by
|
||||
* {@code "#"} (for example, {@code "jdk.VMInfo#period"}). The value
|
||||
* is a textual representation of the settings value (for example,
|
||||
* {@code "60 s"}).
|
||||
*
|
||||
* @param recordingId the ID of the recordings to get settings for
|
||||
*
|
||||
* @return a map that describes the recording settings, not {@code null}
|
||||
*
|
||||
* @throws IllegalArgumentException if no recording with the specified ID exists
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("monitor")}
|
||||
*/
|
||||
Map<String, String> getRecordingSettings(long recordingId) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Sets a configuration as a string representation for the recording with the
|
||||
* specified ID.
|
||||
*
|
||||
* @param recordingId ID of the recording
|
||||
* @param contents a string representation of the configuration file to use,
|
||||
* not {@code null}
|
||||
* @throws IllegalArgumentException if no recording with the
|
||||
* specified ID exists or if the configuration could not be parsed.
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see Configuration#getContents()
|
||||
*/
|
||||
void setConfiguration(long recordingId, String contents) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Sets a predefined configuration for the recording with the specified ID.
|
||||
*
|
||||
* @param recordingId ID of the recording to set the configuration for
|
||||
* @param configurationName the name of the configuration (for example,
|
||||
* {@code "profile"} or {@code "default"}), not {@code null}
|
||||
* @throws IllegalArgumentException if no recording with the
|
||||
* specified ID exists
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see #getConfigurations()
|
||||
*/
|
||||
void setPredefinedConfiguration(long recordingId, String configurationName) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Sets and replaces all previous settings for the specified recording.
|
||||
* <p>
|
||||
* A setting consists of a name/value pair, where <em>name</em> specifies the
|
||||
* event and setting to configure, and the <em>value</em> specifies what to set
|
||||
* it to.
|
||||
* <p>
|
||||
* The name can be formed in the following ways:
|
||||
* <p>
|
||||
* {@code
|
||||
* <event-name> + "#" + <setting-name>
|
||||
* }
|
||||
* <p>
|
||||
* or
|
||||
* <p>
|
||||
* {@code
|
||||
* <event-id> + "#" + <setting-name>
|
||||
* }
|
||||
* <p>
|
||||
* For example, to set the sample interval of the CPU Load event to once every
|
||||
* second, use the name {@code "jdk.CPULoad#period"} and the value
|
||||
* {@code "1 s"}. If multiple events use the same name, for example if an event
|
||||
* class is loaded in multiple class loaders, and differentiation is needed
|
||||
* between them, then the name is {@code "56#period"}. The ID for an event is
|
||||
* obtained by invoking {@link jdk.jfr.EventType#getId()} method and is valid
|
||||
* for the Java Virtual Machine (JVM) instance that the event is registered in.
|
||||
* <p>
|
||||
* A list of available event names is retrieved by invoking
|
||||
* {@link jdk.jfr.FlightRecorder#getEventTypes()} and
|
||||
* {@link jdk.jfr.EventType#getName()}. A list of available settings for an
|
||||
* event type is obtained by invoking
|
||||
* {@link jdk.jfr.EventType#getSettingDescriptors()} and
|
||||
* {@link jdk.jfr.ValueDescriptor#getName()}.
|
||||
*
|
||||
* @param recordingId ID of the recording
|
||||
*
|
||||
* @param settings name value map of the settings to set, not {@code null}
|
||||
*
|
||||
* @throws IllegalArgumentException if no recording with the specified ID exists
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("control")}
|
||||
*
|
||||
* @see Recording#getId()
|
||||
*/
|
||||
void setRecordingSettings(long recordingId, Map<String, String> settings) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Configures the recording options (for example, destination file and time span
|
||||
* to keep data).
|
||||
* <p>
|
||||
* See {@link FlightRecorderMXBean} for a description of the options and values
|
||||
* that can be used. Setting a value to {@code null} restores the value to the
|
||||
* default value.
|
||||
*
|
||||
* @param recordingId the ID of the recording to set options for
|
||||
*
|
||||
* @param options name/value map of the settings to set, not {@code null}
|
||||
*
|
||||
* @throws IllegalArgumentException if no recording with the specified ID exists
|
||||
* @throws java.lang.SecurityException if a security manager exists, and the
|
||||
* caller does not have {@code ManagementPermission("control")} or an
|
||||
* option contains a file that the caller does not have permission to
|
||||
* operate on.
|
||||
* @see Recording#getId()
|
||||
*/
|
||||
void setRecordingOptions(long recordingId, Map<String, String> options) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Returns the list of the available recordings, not necessarily running.
|
||||
* <p>
|
||||
* <b>MBeanServer access</b>:<br>
|
||||
* The mapped type of {@code RecordingInfo} is {@code CompositeData} with
|
||||
* attributes as specified in the {@link RecordingInfo#from
|
||||
* RecordingInfo.from} method.
|
||||
*
|
||||
* @return list of recordings, not {@code null}
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("monitor")}
|
||||
*
|
||||
* @see RecordingInfo
|
||||
* @see Recording
|
||||
*/
|
||||
List<RecordingInfo> getRecordings();
|
||||
|
||||
/**
|
||||
* Returns the list of predefined configurations for this Java Virtual Machine (JVM).
|
||||
* <p>
|
||||
* <b>MBeanServer access</b>:<br>
|
||||
* The mapped type of {@code ConfigurationInfo} is {@code CompositeData}
|
||||
* with attributes as specified in the {@link ConfigurationInfo#from
|
||||
* ConfigurationInfo.from} method.
|
||||
*
|
||||
* @return the list of predefined configurations, not {@code null}
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("monitor")}
|
||||
*
|
||||
* @see ConfigurationInfo
|
||||
* @see Configuration
|
||||
*/
|
||||
List<ConfigurationInfo> getConfigurations();
|
||||
|
||||
/**
|
||||
* Returns the list of currently registered event types.
|
||||
* <p>
|
||||
* <b>MBeanServer access</b>:<br>
|
||||
* The mapped type of {@code EventTypeInfo} is {@code CompositeData} with
|
||||
* attributes as specified in the {@link EventTypeInfo#from
|
||||
* EventTypeInfo.from} method.
|
||||
*
|
||||
* @return the list of registered event types, not {@code null}
|
||||
*
|
||||
* @throws java.lang.SecurityException if a security manager exists and the
|
||||
* caller does not have {@code ManagementPermission("monitor")}
|
||||
*
|
||||
* @see EventTypeInfo
|
||||
* @see EventType
|
||||
*/
|
||||
List<EventTypeInfo> getEventTypes();
|
||||
|
||||
/**
|
||||
* Writes recording data to the specified file.
|
||||
* <p>
|
||||
* If this method is invoked remotely from another process, the data is written
|
||||
* to a file named {@code outputFile} on the machine where the target Java
|
||||
* Virtual Machine (JVM) is running. If the file location is a relative path, it
|
||||
* is relative to the working directory where the target JVM was started.
|
||||
*
|
||||
* @param recordingId the ID of the recording to dump data for
|
||||
*
|
||||
* @param outputFile the system-dependent file name where data is written, not
|
||||
* {@code null}
|
||||
*
|
||||
* @throws IOException if the recording can't be dumped due to an I/O error (for
|
||||
* example, an invalid path)
|
||||
*
|
||||
* @throws IllegalArgumentException if a recording with the specified ID doesn't
|
||||
* exist
|
||||
*
|
||||
* @throws IllegalStateException if the recording is not yet started or if it is
|
||||
* already closed
|
||||
*
|
||||
* @throws SecurityException if a security manager exists and its
|
||||
* {@code SecurityManager.checkWrite(java.lang.String)} method denies
|
||||
* write access to the named file or the caller does not have
|
||||
* {@code ManagmentPermission("control")}
|
||||
*
|
||||
* @see java.nio.file.Path#toString()
|
||||
* @see Recording#dump(java.nio.file.Path)
|
||||
*/
|
||||
void copyTo(long recordingId, String outputFile) throws IOException, SecurityException;
|
||||
}
|
||||
440
jdkSrc/jdk8/jdk/management/jfr/FlightRecorderMXBeanImpl.java
Normal file
440
jdkSrc/jdk8/jdk/management/jfr/FlightRecorderMXBeanImpl.java
Normal file
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import javax.management.AttributeChangeNotification;
|
||||
import javax.management.AttributeNotFoundException;
|
||||
import javax.management.ListenerNotFoundException;
|
||||
import javax.management.MBeanException;
|
||||
import javax.management.MBeanNotificationInfo;
|
||||
import javax.management.Notification;
|
||||
import javax.management.NotificationBroadcasterSupport;
|
||||
import javax.management.NotificationEmitter;
|
||||
import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.ReflectionException;
|
||||
import javax.management.StandardEmitterMBean;
|
||||
|
||||
import jdk.jfr.Configuration;
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.FlightRecorder;
|
||||
import jdk.jfr.FlightRecorderListener;
|
||||
import jdk.jfr.FlightRecorderPermission;
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.jfr.RecordingState;
|
||||
import jdk.jfr.internal.management.ManagementSupport;
|
||||
|
||||
// Instantiated by service provider
|
||||
final class FlightRecorderMXBeanImpl extends StandardEmitterMBean implements FlightRecorderMXBean, NotificationEmitter {
|
||||
|
||||
final class MXBeanListener implements FlightRecorderListener {
|
||||
private final NotificationListener listener;
|
||||
private final NotificationFilter filter;
|
||||
private final Object handback;
|
||||
private final AccessControlContext context;
|
||||
|
||||
public MXBeanListener(NotificationListener listener, NotificationFilter filter, Object handback) {
|
||||
this.context = AccessController.getContext();
|
||||
this.listener = listener;
|
||||
this.filter = filter;
|
||||
this.handback = handback;
|
||||
}
|
||||
|
||||
public void recordingStateChanged(Recording recording) {
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
sendNotification(createNotication(recording));
|
||||
return null;
|
||||
}
|
||||
}, context);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String ATTRIBUTE_RECORDINGS = "Recordings";
|
||||
private static final String OPTION_MAX_SIZE = "maxSize";
|
||||
private static final String OPTION_MAX_AGE = "maxAge";
|
||||
private static final String OPTION_NAME = "name";
|
||||
private static final String OPTION_DISK = "disk";
|
||||
private static final String OPTION_DUMP_ON_EXIT = "dumpOnExit";
|
||||
private static final String OPTION_DURATION = "duration";
|
||||
private static final List<String> OPTIONS = Arrays.asList(new String[] { OPTION_DUMP_ON_EXIT, OPTION_DURATION, OPTION_NAME, OPTION_MAX_AGE, OPTION_MAX_SIZE, OPTION_DISK, });
|
||||
private final StreamManager streamHandler = new StreamManager();
|
||||
private final Map<Long, Object> changes = new ConcurrentHashMap<>();
|
||||
private final AtomicLong sequenceNumber = new AtomicLong();
|
||||
private final List<MXBeanListener> listeners = new CopyOnWriteArrayList<>();
|
||||
private FlightRecorder recorder;
|
||||
|
||||
FlightRecorderMXBeanImpl() {
|
||||
super(FlightRecorderMXBean.class, true, new NotificationBroadcasterSupport(createNotificationInfo()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRecording(long id) {
|
||||
MBeanUtils.checkControl();
|
||||
getExistingRecording(id).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean stopRecording(long id) {
|
||||
MBeanUtils.checkControl();
|
||||
return getExistingRecording(id).stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeRecording(long id) {
|
||||
MBeanUtils.checkControl();
|
||||
getExistingRecording(id).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long openStream(long id, Map<String, String> options) throws IOException {
|
||||
MBeanUtils.checkControl();
|
||||
if (!FlightRecorder.isInitialized()) {
|
||||
throw new IllegalArgumentException("No recording available with id " + id);
|
||||
}
|
||||
// Make local copy to prevent concurrent modification
|
||||
Map<String, String> s = options == null ? new HashMap<>() : new HashMap<>(options);
|
||||
Instant starttime = MBeanUtils.parseTimestamp(s.get("startTime"), Instant.MIN);
|
||||
Instant endtime = MBeanUtils.parseTimestamp(s.get("endTime"), Instant.MAX);
|
||||
int blockSize = MBeanUtils.parseBlockSize(s.get("blockSize"), StreamManager.DEFAULT_BLOCK_SIZE);
|
||||
InputStream is = getExistingRecording(id).getStream(starttime, endtime);
|
||||
if (is == null) {
|
||||
throw new IOException("No recording data available");
|
||||
}
|
||||
return streamHandler.create(is, blockSize).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeStream(long streamIdentifier) throws IOException {
|
||||
MBeanUtils.checkControl();
|
||||
streamHandler.getStream(streamIdentifier).close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] readStream(long streamIdentifier) throws IOException {
|
||||
MBeanUtils.checkMonitor();
|
||||
return streamHandler.getStream(streamIdentifier).read();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RecordingInfo> getRecordings() {
|
||||
MBeanUtils.checkMonitor();
|
||||
if (!FlightRecorder.isInitialized()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return MBeanUtils.transformList(getRecorder().getRecordings(), RecordingInfo::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ConfigurationInfo> getConfigurations() {
|
||||
MBeanUtils.checkMonitor();
|
||||
return MBeanUtils.transformList(Configuration.getConfigurations(), ConfigurationInfo::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EventTypeInfo> getEventTypes() {
|
||||
MBeanUtils.checkMonitor();
|
||||
List<EventType> eventTypes = AccessController.doPrivileged(new PrivilegedAction<List<EventType>>() {
|
||||
@Override
|
||||
public List<EventType> run() {
|
||||
return ManagementSupport.getEventTypes();
|
||||
}
|
||||
}, null, new FlightRecorderPermission("accessFlightRecorder"));
|
||||
|
||||
return MBeanUtils.transformList(eventTypes, EventTypeInfo::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getRecordingSettings(long recording) throws IllegalArgumentException {
|
||||
MBeanUtils.checkMonitor();
|
||||
return getExistingRecording(recording).getSettings();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecordingSettings(long recording, Map<String, String> values) throws IllegalArgumentException {
|
||||
Objects.requireNonNull(values);
|
||||
MBeanUtils.checkControl();
|
||||
getExistingRecording(recording).setSettings(values);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long newRecording() {
|
||||
MBeanUtils.checkControl();
|
||||
getRecorder(); // ensure notification listener is setup
|
||||
return AccessController.doPrivileged(new PrivilegedAction<Recording>() {
|
||||
@Override
|
||||
public Recording run() {
|
||||
return new Recording();
|
||||
}
|
||||
}, null, new FlightRecorderPermission("accessFlightRecorder")).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long takeSnapshot() {
|
||||
MBeanUtils.checkControl();
|
||||
return getRecorder().takeSnapshot().getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setConfiguration(long recording, String configuration) throws IllegalArgumentException {
|
||||
Objects.requireNonNull(configuration);
|
||||
MBeanUtils.checkControl();
|
||||
try {
|
||||
Configuration c = Configuration.create(new StringReader(configuration));
|
||||
getExistingRecording(recording).setSettings(c.getSettings());
|
||||
} catch (IOException | ParseException e) {
|
||||
throw new IllegalArgumentException("Could not parse configuration", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPredefinedConfiguration(long recording, String configurationName) throws IllegalArgumentException {
|
||||
Objects.requireNonNull(configurationName);
|
||||
MBeanUtils.checkControl();
|
||||
Recording r = getExistingRecording(recording);
|
||||
for (Configuration c : Configuration.getConfigurations()) {
|
||||
if (c.getName().equals(configurationName)) {
|
||||
r.setSettings(c.getSettings());
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Could not find configuration with name " + configurationName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyTo(long recording, String path) throws IOException {
|
||||
Objects.requireNonNull(path);
|
||||
MBeanUtils.checkControl();
|
||||
getExistingRecording(recording).dump(Paths.get(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecordingOptions(long recording, Map<String, String> options) throws IllegalArgumentException {
|
||||
Objects.requireNonNull(options);
|
||||
MBeanUtils.checkControl();
|
||||
// Make local copy to prevent concurrent modification
|
||||
Map<String, String> ops = new HashMap<String, String>(options);
|
||||
for (Map.Entry<String, String> entry : ops.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
if (!(key instanceof String)) {
|
||||
throw new IllegalArgumentException("Option key must not be null, or other type than " + String.class);
|
||||
}
|
||||
if (!OPTIONS.contains(key)) {
|
||||
throw new IllegalArgumentException("Unknown recording option: " + key + ". Valid options are " + OPTIONS + ".");
|
||||
}
|
||||
if (value != null && !(value instanceof String)) {
|
||||
throw new IllegalArgumentException("Incorrect value for option " + key + ". Values must be of type " + String.class + " .");
|
||||
}
|
||||
}
|
||||
|
||||
Recording r = getExistingRecording(recording);
|
||||
validateOption(ops, OPTION_DUMP_ON_EXIT, MBeanUtils::booleanValue);
|
||||
validateOption(ops, OPTION_DISK, MBeanUtils::booleanValue);
|
||||
validateOption(ops, OPTION_NAME, Function.identity());
|
||||
validateOption(ops, OPTION_MAX_AGE, MBeanUtils::duration);
|
||||
validateOption(ops, OPTION_MAX_SIZE, MBeanUtils::size);
|
||||
validateOption(ops, OPTION_DURATION, MBeanUtils::duration);
|
||||
|
||||
// All OK, now set them.atomically
|
||||
setOption(ops, OPTION_DUMP_ON_EXIT, "false", MBeanUtils::booleanValue, x -> r.setDumpOnExit(x));
|
||||
setOption(ops, OPTION_DISK, "true", MBeanUtils::booleanValue, x -> r.setToDisk(x));
|
||||
setOption(ops, OPTION_NAME, String.valueOf(r.getId()), Function.identity(), x -> r.setName(x));
|
||||
setOption(ops, OPTION_MAX_AGE, null, MBeanUtils::duration, x -> r.setMaxAge(x));
|
||||
setOption(ops, OPTION_MAX_SIZE, "0", MBeanUtils::size, x -> r.setMaxSize(x));
|
||||
setOption(ops, OPTION_DURATION, null, MBeanUtils::duration, x -> r.setDuration(x));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, String> getRecordingOptions(long recording) throws IllegalArgumentException {
|
||||
MBeanUtils.checkMonitor();
|
||||
Recording r = getExistingRecording(recording);
|
||||
Map<String, String> options = new HashMap<>(10);
|
||||
options.put(OPTION_DUMP_ON_EXIT, String.valueOf(r.getDumpOnExit()));
|
||||
options.put(OPTION_DISK, String.valueOf(r.isToDisk()));
|
||||
options.put(OPTION_NAME, String.valueOf(r.getName()));
|
||||
options.put(OPTION_MAX_AGE, ManagementSupport.formatTimespan(r.getMaxAge(), " "));
|
||||
Long maxSize = r.getMaxSize();
|
||||
options.put(OPTION_MAX_SIZE, String.valueOf(maxSize == null ? "0" : maxSize.toString()));
|
||||
options.put(OPTION_DURATION, ManagementSupport.formatTimespan(r.getDuration(), " "));
|
||||
return options;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long cloneRecording(long id, boolean stop) throws IllegalStateException, SecurityException {
|
||||
MBeanUtils.checkControl();
|
||||
return getRecording(id).copy(stop).getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectName getObjectName() {
|
||||
return MBeanUtils.createObjectName();
|
||||
}
|
||||
|
||||
private Recording getExistingRecording(long id) {
|
||||
if (FlightRecorder.isInitialized()) {
|
||||
Recording recording = getRecording(id);
|
||||
if (recording != null) {
|
||||
return recording;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No recording available with id " + id);
|
||||
}
|
||||
|
||||
private Recording getRecording(long id) {
|
||||
List<Recording> recs = getRecorder().getRecordings();
|
||||
return recs.stream().filter(r -> r.getId() == id).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private static <T, U> void setOption(Map<String, String> options, String name, String defaultValue, Function<String, U> converter, Consumer<U> setter) {
|
||||
if (!options.containsKey(name)) {
|
||||
return;
|
||||
}
|
||||
String v = options.get(name);
|
||||
if (v == null) {
|
||||
v = defaultValue;
|
||||
}
|
||||
try {
|
||||
setter.accept(converter.apply(v));
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new IllegalArgumentException("Not a valid value for option '" + name + "'. " + iae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static <T, U> void validateOption(Map<String, String> options, String name, Function<String, U> validator) {
|
||||
try {
|
||||
String v = options.get(name);
|
||||
if (v == null) {
|
||||
return; // OK, will set default
|
||||
}
|
||||
validator.apply(v);
|
||||
} catch (IllegalArgumentException iae) {
|
||||
throw new IllegalArgumentException("Not a valid value for option '" + name + "'. " + iae.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private FlightRecorder getRecorder() throws SecurityException {
|
||||
// Synchronize on some private object that is always available
|
||||
synchronized (streamHandler) {
|
||||
if (recorder == null) {
|
||||
recorder = AccessController.doPrivileged(new PrivilegedAction<FlightRecorder>() {
|
||||
@Override
|
||||
public FlightRecorder run() {
|
||||
return FlightRecorder.getFlightRecorder();
|
||||
}
|
||||
}, null, new FlightRecorderPermission("accessFlightRecorder"));
|
||||
}
|
||||
return recorder;
|
||||
}
|
||||
}
|
||||
|
||||
private static MBeanNotificationInfo[] createNotificationInfo() {
|
||||
String[] types = new String[] { AttributeChangeNotification.ATTRIBUTE_CHANGE };
|
||||
String name = AttributeChangeNotification.class.getName();
|
||||
String description = "Notifies if the RecordingState has changed for one of the recordings, for example if a recording starts or stops";
|
||||
MBeanNotificationInfo info = new MBeanNotificationInfo(types, name, description);
|
||||
return new MBeanNotificationInfo[] { info };
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
|
||||
MXBeanListener mxbeanListener = new MXBeanListener(listener, filter, handback);
|
||||
listeners.add(mxbeanListener);
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
@Override
|
||||
public Void run(){
|
||||
FlightRecorder.addListener(mxbeanListener);
|
||||
return null;
|
||||
}
|
||||
}, null, new FlightRecorderPermission("accessFlightRecorder"));
|
||||
super.addNotificationListener(listener, filter, handback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
|
||||
removeListeners( x -> listener == x.listener);
|
||||
super.removeNotificationListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
|
||||
removeListeners( x -> listener == x.listener && filter == x.filter && handback == x.handback);
|
||||
super.removeNotificationListener(listener, filter, handback);
|
||||
}
|
||||
|
||||
private void removeListeners(Predicate<MXBeanListener> p) {
|
||||
List<MXBeanListener> toBeRemoved = new ArrayList<>(listeners.size());
|
||||
for (MXBeanListener l : listeners) {
|
||||
if (p.test(l)) {
|
||||
toBeRemoved.add(l);
|
||||
FlightRecorder.removeListener(l);
|
||||
}
|
||||
}
|
||||
listeners.removeAll(toBeRemoved);
|
||||
}
|
||||
|
||||
private Notification createNotication(Recording recording) {
|
||||
try {
|
||||
Long id = recording.getId();
|
||||
Object oldValue = changes.get(recording.getId());
|
||||
Object newValue = getAttribute(ATTRIBUTE_RECORDINGS);
|
||||
if (recording.getState() != RecordingState.CLOSED) {
|
||||
changes.put(id, newValue);
|
||||
} else {
|
||||
changes.remove(id);
|
||||
}
|
||||
return new AttributeChangeNotification(getObjectName(), sequenceNumber.incrementAndGet(), System.currentTimeMillis(), "Recording " + recording.getName() + " is "
|
||||
+ recording.getState(), ATTRIBUTE_RECORDINGS, newValue.getClass().getName(), oldValue, newValue);
|
||||
} catch (AttributeNotFoundException | MBeanException | ReflectionException e) {
|
||||
throw new RuntimeException("Could not create notifcation for FlightRecorderMXBean. " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
130
jdkSrc/jdk8/jdk/management/jfr/MBeanUtils.java
Normal file
130
jdkSrc/jdk8/jdk/management/jfr/MBeanUtils.java
Normal file
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.lang.management.ManagementPermission;
|
||||
import java.security.Permission;
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.management.MalformedObjectNameException;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import jdk.jfr.internal.management.ManagementSupport;
|
||||
|
||||
final class MBeanUtils {
|
||||
|
||||
private static final Permission monitor = new ManagementPermission("monitor");
|
||||
private static final Permission control = new ManagementPermission("control");
|
||||
|
||||
static ObjectName createObjectName() {
|
||||
try {
|
||||
return new ObjectName(FlightRecorderMXBean.MXBEAN_NAME);
|
||||
} catch (MalformedObjectNameException mne) {
|
||||
throw new Error("Can't happen", mne);
|
||||
}
|
||||
}
|
||||
|
||||
static void checkControl() {
|
||||
SecurityManager secManager = System.getSecurityManager();
|
||||
if (secManager != null) {
|
||||
secManager.checkPermission(control);
|
||||
}
|
||||
}
|
||||
|
||||
static void checkMonitor() {
|
||||
SecurityManager secManager = System.getSecurityManager();
|
||||
if (secManager != null) {
|
||||
secManager.checkPermission(monitor);
|
||||
}
|
||||
}
|
||||
|
||||
static <T, R> List<R> transformList(List<T> source, Function<T, R> function) {
|
||||
return source.stream().map(function).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
static boolean booleanValue(String s) {
|
||||
if ("true".equals(s)) {
|
||||
return true;
|
||||
}
|
||||
if ("false".equals(s)) {
|
||||
return false;
|
||||
}
|
||||
throw new IllegalArgumentException("Value must be true or false.");
|
||||
}
|
||||
|
||||
static Duration duration(String s) throws NumberFormatException {
|
||||
if (s == null) {
|
||||
return null;
|
||||
}
|
||||
long l = ManagementSupport.parseTimespan(s);
|
||||
if (l == 0) {
|
||||
return null;
|
||||
}
|
||||
return Duration.ofNanos(l);
|
||||
}
|
||||
|
||||
public static Instant parseTimestamp(String s, Instant defaultValue) {
|
||||
if (s == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
try {
|
||||
return Instant.parse(s);
|
||||
} catch(DateTimeParseException e ) {
|
||||
// OK, try with milliseconds since epoch
|
||||
// before giving up.
|
||||
}
|
||||
try {
|
||||
return Instant.ofEpochMilli(Long.parseLong(s));
|
||||
} catch (NumberFormatException | DateTimeException nfr) {
|
||||
throw new IllegalArgumentException("Not a valid timestamp " + s);
|
||||
}
|
||||
}
|
||||
|
||||
static Long size(String s) throws NumberFormatException {
|
||||
long size = Long.parseLong(s);
|
||||
if (size < 0) {
|
||||
throw new IllegalArgumentException("Negative size not allowed");
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
public static int parseBlockSize(String string, int defaultSize) {
|
||||
if (string == null) {
|
||||
return defaultSize;
|
||||
}
|
||||
int size = Integer.parseInt(string);
|
||||
if (size <1) {
|
||||
throw new IllegalArgumentException("Block size must be at least 1 byte");
|
||||
}
|
||||
return size;
|
||||
}
|
||||
}
|
||||
|
||||
397
jdkSrc/jdk8/jdk/management/jfr/RecordingInfo.java
Normal file
397
jdkSrc/jdk8/jdk/management/jfr/RecordingInfo.java
Normal file
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import javax.management.openmbean.TabularData;
|
||||
|
||||
import jdk.jfr.Recording;
|
||||
import jdk.jfr.RecordingState;
|
||||
import jdk.jfr.internal.management.ManagementSupport;
|
||||
|
||||
/**
|
||||
* Management representation of a {@code Recording}.
|
||||
*
|
||||
* @see Recording
|
||||
*
|
||||
* @since 8
|
||||
*/
|
||||
public final class RecordingInfo {
|
||||
private final long id;
|
||||
private final String name;
|
||||
private final String state;
|
||||
private final boolean dumpOnExit;
|
||||
private final long size;
|
||||
private final boolean disk;
|
||||
private final long maxAge;
|
||||
private final long maxSize;
|
||||
private final long startTime;
|
||||
private final long stopTime;
|
||||
private final String destination;
|
||||
private final long durationInSeconds;
|
||||
private final Map<String, String> settings;
|
||||
|
||||
// package private
|
||||
RecordingInfo(Recording recording) {
|
||||
id = recording.getId();
|
||||
name = recording.getName();
|
||||
state = recording.getState().toString();
|
||||
dumpOnExit = recording.getDumpOnExit();
|
||||
size = recording.getSize();
|
||||
disk = recording.isToDisk();
|
||||
|
||||
Duration d = recording.getMaxAge();
|
||||
if (d == null) {
|
||||
maxAge = 0;
|
||||
} else {
|
||||
maxAge = d.getSeconds();
|
||||
}
|
||||
maxSize = recording.getMaxSize();
|
||||
Instant s = recording.getStartTime();
|
||||
startTime = s == null ? 0L : s.toEpochMilli();
|
||||
Instant st = recording.getStopTime();
|
||||
stopTime = st == null ? 0L : st.toEpochMilli();
|
||||
destination = ManagementSupport.getDestinationOriginalText(recording);
|
||||
Duration duration = recording.getDuration();
|
||||
durationInSeconds = duration == null ? 0 : duration.getSeconds();
|
||||
settings = recording.getSettings();
|
||||
}
|
||||
|
||||
private RecordingInfo(CompositeData cd) {
|
||||
id = (int) 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");
|
||||
maxAge = (Long) cd.get("maxAge");
|
||||
maxSize = (Long) cd.get("maxSize");
|
||||
startTime = (Long) cd.get("startTime");
|
||||
stopTime = (Long) cd.get("stopTime");
|
||||
destination = (String) cd.get("destination");
|
||||
durationInSeconds = (long) cd.get("duration");
|
||||
settings = new LinkedHashMap<>();
|
||||
Object map = cd.get("settings");
|
||||
if (map instanceof TabularData) {
|
||||
TabularData td = (TabularData) map;
|
||||
List<String> keyNames = td.getTabularType().getIndexNames();
|
||||
int size = keyNames.size();
|
||||
for (Object keys : td.keySet()) {
|
||||
Object[] keyValues = ((List<?>) keys).toArray();
|
||||
for (int i = 0; i < size; i++) {
|
||||
String key = keyNames.get(i);
|
||||
Object value = keyValues[i];
|
||||
if (value instanceof String) {
|
||||
settings.put(key, (String) value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the recording associated with this
|
||||
* {@code RecordingInfo}.
|
||||
*
|
||||
* @return the recording name, not {@code null}
|
||||
*
|
||||
* @see Recording#getName()
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the unique ID for the recording associated with this
|
||||
* {@code RecordingInfo}.
|
||||
*
|
||||
* @return the recording ID
|
||||
*
|
||||
* @see Recording#getId()
|
||||
*/
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the recording associated with this {@code RecordingInfo}
|
||||
* should be dumped to file when the JVM exits.
|
||||
*
|
||||
* @return {@code true} if recording should be dumped on exit, {@code false}
|
||||
* otherwise
|
||||
*
|
||||
* @see Recording#getDumpOnExit()
|
||||
*/
|
||||
public boolean getDumpOnExit() {
|
||||
return dumpOnExit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns how many seconds data should be kept on disk, or {@code 0} if
|
||||
* data is to be kept forever.
|
||||
* <p>
|
||||
* In-memory recordings are not affected by maximum age.
|
||||
*
|
||||
* @see Recording#getMaxAge()
|
||||
* @see Recording#setToDisk(boolean)
|
||||
* @return how long data should be kept on disk, measured in seconds
|
||||
*
|
||||
*/
|
||||
public long getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount of data, measured in bytes, the recording associated
|
||||
* with this {@code RecordingInfo}, should be kept on disk, before it's
|
||||
* rotated away, or {@code 0} if data is to be kept indefinitely.
|
||||
* <p>
|
||||
* In-memory recordings are not affected by maximum size.
|
||||
*
|
||||
* @return the amount of data should be kept on disk, in bytes
|
||||
*
|
||||
* @see Recording#setToDisk(boolean)
|
||||
* @see Recording#getMaxSize()
|
||||
*/
|
||||
public long getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code String} representation of state of the recording
|
||||
* associated with this {@code RecordingInfo}.
|
||||
* <p>
|
||||
* Valid return values are {@code "NEW"}, {@code "DELAYED"}, {@code "STARTING"},
|
||||
* {@code "RUNNING"}, {@code "STOPPING"}, {@code "STOPPED"} and {@code "CLOSED"}.
|
||||
*
|
||||
* @return the recording state, not {@code null}
|
||||
*
|
||||
* @see RecordingState#toString()
|
||||
* @see Recording#getState()
|
||||
*/
|
||||
public String getState() {
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns start time of the recording associated with this
|
||||
* {@code RecordingInfo}, measured as ms since epoch, or {@code null} if the
|
||||
* recording hasn't started.
|
||||
*
|
||||
* @return the start time of the recording, or {@code null} if the recording
|
||||
* hasn't started
|
||||
*
|
||||
* @see Recording#getStartTime()
|
||||
*/
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual or expected stop time of the recording associated with
|
||||
* this {@code RecordingInfo}, measured as ms since epoch, or {@code null}
|
||||
* if the expected or actual stop time is not known, which can only happen
|
||||
* if the recording has not yet been stopped.
|
||||
*
|
||||
* @return the stop time of recording, or {@code null} if recording hasn't
|
||||
* been stopped.
|
||||
*
|
||||
* @see Recording#getStopTime()
|
||||
*/
|
||||
public long getStopTime() {
|
||||
return stopTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the settings for the recording associated with this
|
||||
* {@code RecordingInfo}.
|
||||
*
|
||||
* @return the recording settings, not {@code null}
|
||||
*
|
||||
* @see Recording#getSettings()
|
||||
*/
|
||||
public Map<String, String> getSettings() {
|
||||
return settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns destination path where data, for the recording associated with
|
||||
* this {@link RecordingInfo}, should be written when the recording stops,
|
||||
* or {@code null} if the recording should not be written.
|
||||
*
|
||||
* @return the destination, or {@code null} if not set
|
||||
*
|
||||
* @see Recording#getDestination()
|
||||
*/
|
||||
public String getDestination() {
|
||||
return destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string description of the recording associated with this
|
||||
* {@code RecordingInfo}
|
||||
*
|
||||
* @return description, not {@code null}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
Stringifier s = new Stringifier();
|
||||
s.add("name", name);
|
||||
s.add("id", id);
|
||||
s.add("maxAge", maxAge);
|
||||
s.add("maxSize", maxSize);
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the amount data recorded by recording. associated with this
|
||||
* {@link RecordingInfo}.
|
||||
*
|
||||
* @return the amount of recorded data, measured in bytes
|
||||
*/
|
||||
public long getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the recording associated with this
|
||||
* {@code RecordingInfo} should be flushed to disk, when memory buffers are
|
||||
* full, {@code false} otherwise.
|
||||
*
|
||||
* @return {@code true} if recording is to disk, {@code false} otherwise
|
||||
*/
|
||||
public boolean isToDisk() {
|
||||
return disk;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the desired duration, measured in seconds, of the recording
|
||||
* associated with this {@link RecordingInfo}, or {code 0} if no duration
|
||||
* has been set.
|
||||
*
|
||||
* @return the desired duration, or {code 0} if no duration has been set
|
||||
*
|
||||
* @see Recording#getDuration()
|
||||
*/
|
||||
public long getDuration() {
|
||||
return durationInSeconds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code RecordingInfo} represented by the specified
|
||||
* {@code CompositeData} object.
|
||||
* <p>
|
||||
* The specified {@code CompositeData} must have the following item names and
|
||||
* item types to be valid. <blockquote>
|
||||
* <table class="striped">
|
||||
* <caption>Supported names and types in a specified {@code CompositeData} object</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col" style="text-align:left">Name</th>
|
||||
* <th scope="col" style="text-align:left">Type</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th scope="row">id</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">name</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">state</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">dumpOnExit</th>
|
||||
* <td>{@code Boolean}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">size</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">disk</th>
|
||||
* <td>{@code Boolean}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">maxAge</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">maxSize</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">startTime</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">stopTime</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">destination</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">duration</th>
|
||||
* <td>{@code Long}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">settings</th>
|
||||
* <td>{@code javax.management.openmbean.CompositeData[]} whose element type
|
||||
* is the mapped type for {@link SettingDescriptorInfo} as specified in the
|
||||
* {@link SettingDescriptorInfo#from} method.</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* @param cd {@code CompositeData} representing the {@code RecordingInfo} to
|
||||
* return
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code cd} does not represent a valid
|
||||
* {@code RecordingInfo}
|
||||
*
|
||||
* @return the {@code RecordingInfo} represented by {@code cd}, or
|
||||
* {@code null} if {@code cd} is {@code null}
|
||||
*/
|
||||
public static RecordingInfo from(CompositeData cd) {
|
||||
if (cd == null) {
|
||||
return null;
|
||||
}
|
||||
return new RecordingInfo(cd);
|
||||
}
|
||||
}
|
||||
232
jdkSrc/jdk8/jdk/management/jfr/SettingDescriptorInfo.java
Normal file
232
jdkSrc/jdk8/jdk/management/jfr/SettingDescriptorInfo.java
Normal file
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import javax.management.openmbean.CompositeData;
|
||||
|
||||
import jdk.jfr.EventType;
|
||||
import jdk.jfr.SettingDescriptor;
|
||||
import jdk.management.jfr.internal.FlightRecorderMXBeanProvider;
|
||||
|
||||
/**
|
||||
* Management class that describes a setting, for example name, description and
|
||||
* default value.
|
||||
*
|
||||
* @see EventType#getSettingDescriptors()
|
||||
*
|
||||
* @since 8
|
||||
*/
|
||||
public final class SettingDescriptorInfo {
|
||||
|
||||
// Purpose of this static initializer is to allow
|
||||
// FlightRecorderMXBeanProvider
|
||||
// to be in an internal package and not visible, but at the same time allow
|
||||
// it to instantiate FlightRecorderMXBeanImpl.
|
||||
//
|
||||
// The reason the mechanism is in this class is because it is light weight
|
||||
// and can easily be triggered from FlightRecorderMXBeanProvider.
|
||||
static {
|
||||
FlightRecorderMXBeanProvider.setFlightRecorderMXBeanFactory(new Callable<FlightRecorderMXBean>() {
|
||||
@Override
|
||||
public FlightRecorderMXBean call() throws Exception {
|
||||
return new FlightRecorderMXBeanImpl();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String label;
|
||||
private final String description;
|
||||
private final String typeName;
|
||||
private final String contentType;
|
||||
private final String defaultValue;
|
||||
|
||||
// package private
|
||||
SettingDescriptorInfo(SettingDescriptor settingDescriptor) {
|
||||
this.name = settingDescriptor.getName();
|
||||
this.label = settingDescriptor.getLabel();
|
||||
this.description = settingDescriptor.getDescription();
|
||||
this.typeName = settingDescriptor.getTypeName();
|
||||
this.contentType = settingDescriptor.getContentType();
|
||||
this.defaultValue = settingDescriptor.getDefaultValue();
|
||||
}
|
||||
|
||||
private SettingDescriptorInfo(CompositeData cd) {
|
||||
this.name = (String) cd.get("name");
|
||||
this.label = (String) cd.get("label");
|
||||
this.description = (String) cd.get("description");
|
||||
this.typeName = (String) cd.get("typeName");
|
||||
this.defaultValue = (String) cd.get("defaultValue");
|
||||
this.contentType = (String) cd.get("contentType");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the human-readable name of the setting associated with this
|
||||
* {@code SettingDescriptorInfo} (for example, {@code "Threshold"}).
|
||||
*
|
||||
* @return the label for this setting, not {@code null}
|
||||
*/
|
||||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the setting associated with this
|
||||
* {@code SettingDescriptorInfo} (for example, {@code "threshold"}).
|
||||
*
|
||||
* @return the name of this setting, not {@code null}
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the description of the setting associated this
|
||||
* {@code SettingDescriptorInfo} (for example,
|
||||
* {@code "The duration an event must exceed to be be recorded"}).
|
||||
*
|
||||
* @return the description of this setting, not null
|
||||
*/
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type name of the setting associated this
|
||||
* {@code SettingDescriptorInfo} (for example,
|
||||
* {@code "jdk.settings.Threshold"}).
|
||||
* <p>
|
||||
* The type can be used to identify what type of setting this is.
|
||||
*
|
||||
* @return the name of this settings type, not {@code null}
|
||||
*/
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content type of the setting associated this
|
||||
* {@code SettingDescriptorInfo} (for example, {@code "jdk.jfr.Timespan"}).
|
||||
* <p>
|
||||
* The content type can be used to determine how the setting should be
|
||||
* rendered in a graphical user interface.
|
||||
*
|
||||
* @return the name of this settings type, not {@code null}
|
||||
*/
|
||||
public String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default value of the setting associated this
|
||||
* {@code SettingDescriptorInfo} (for example, {@code "20 ms"}).
|
||||
*
|
||||
* @return default value for this setting, not {@code null}
|
||||
*
|
||||
* @see SettingDescriptor#getDefaultValue()
|
||||
*/
|
||||
public String getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code SettingDescriptorInfo} represented by the specified
|
||||
* {@code CompositeData}
|
||||
* <p>
|
||||
* The supplied {@code CompositeData} must have the following item names and
|
||||
* item types to be valid. <blockquote>
|
||||
* <table class="striped">
|
||||
* <caption>The name and type the specified CompositeData must contain</caption>
|
||||
* <thead>
|
||||
* <tr>
|
||||
* <th scope="col" style="text-align:left">Name</th>
|
||||
* <th scope="col" style="text-align:left">Type</th>
|
||||
* </tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr>
|
||||
* <th scope="row">name</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">label</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">description</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">typeName</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">contentType</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <th scope="row">defaultValue</th>
|
||||
* <td>{@code String}</td>
|
||||
* </tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* </blockquote>
|
||||
*
|
||||
* @param cd {@code CompositeData} representing the {@code SettingDescriptorInfo} to
|
||||
* return
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code cd} does not represent a valid
|
||||
* {@code EventTypeInfo}
|
||||
*
|
||||
* @return a {@code SettingDescriptorInfo}, or {@code null} if {@code cd} is
|
||||
* {@code null}
|
||||
*/
|
||||
public static SettingDescriptorInfo from(CompositeData cd) {
|
||||
if (cd == null) {
|
||||
return null;
|
||||
}
|
||||
return new SettingDescriptorInfo(cd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@code String} description of this {@code SettingDescriptorInfo}.
|
||||
*
|
||||
* @return a string describing this setting, not {@code null}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
Stringifier s = new Stringifier();
|
||||
s.add("name", name);
|
||||
s.add("label", label);
|
||||
s.add("description", description);
|
||||
s.add("typeName", typeName);
|
||||
s.add("contentType", contentType);
|
||||
s.add("defaultValue", defaultValue);
|
||||
return s.toString();
|
||||
}
|
||||
}
|
||||
81
jdkSrc/jdk8/jdk/management/jfr/Stream.java
Normal file
81
jdkSrc/jdk8/jdk/management/jfr/Stream.java
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
final class Stream implements Closeable {
|
||||
|
||||
private final long identifier;
|
||||
private final BufferedInputStream inputStream;
|
||||
private final byte[] buffer;
|
||||
|
||||
private volatile long time;
|
||||
|
||||
Stream(InputStream is, long identifier, int blockSize) {
|
||||
this.inputStream = new BufferedInputStream(is, 50000);
|
||||
this.identifier = identifier;
|
||||
this.buffer = new byte[blockSize];
|
||||
}
|
||||
|
||||
private void touch() {
|
||||
time = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public long getLastTouched() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public byte[] read() throws IOException {
|
||||
// OK to reuse buffer since this
|
||||
// is only used for serialization
|
||||
touch();
|
||||
int read = inputStream.read(buffer);
|
||||
if (read == -1) {
|
||||
// null indicate no more data
|
||||
return null;
|
||||
}
|
||||
if (read != buffer.length) {
|
||||
byte[] smallerBuffer = new byte[read];
|
||||
System.arraycopy(buffer, 0, smallerBuffer, 0, read);
|
||||
return smallerBuffer;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
inputStream.close();
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return identifier;
|
||||
}
|
||||
}
|
||||
50
jdkSrc/jdk8/jdk/management/jfr/StreamCleanupTask.java
Normal file
50
jdkSrc/jdk8/jdk/management/jfr/StreamCleanupTask.java
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.util.TimerTask;
|
||||
|
||||
final class StreamCleanupTask extends TimerTask {
|
||||
|
||||
private final Stream stream;
|
||||
private final StreamManager manager;
|
||||
|
||||
StreamCleanupTask(StreamManager streamManager, Stream stream) {
|
||||
this.stream = stream;
|
||||
this.manager = streamManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
long lastTouched = stream.getLastTouched();
|
||||
long now = System.currentTimeMillis();
|
||||
if (now - lastTouched >= StreamManager.TIME_OUT) {
|
||||
manager.destroy(stream);
|
||||
} else {
|
||||
manager.scheduleAbort(stream, lastTouched + StreamManager.TIME_OUT);
|
||||
}
|
||||
}
|
||||
}
|
||||
82
jdkSrc/jdk8/jdk/management/jfr/StreamManager.java
Normal file
82
jdkSrc/jdk8/jdk/management/jfr/StreamManager.java
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Timer;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
final class StreamManager {
|
||||
|
||||
public static final long TIME_OUT = TimeUnit.MINUTES.toMillis(2);
|
||||
public static final int DEFAULT_BLOCK_SIZE = 50000;
|
||||
|
||||
private static long idCounter = 0;
|
||||
|
||||
private final Map<Long, Stream> streams = new HashMap<>();
|
||||
private Timer timer;
|
||||
|
||||
public synchronized Stream getStream(long streamIdentifer) {
|
||||
Stream stream = streams.get(streamIdentifer);
|
||||
if (stream == null) {
|
||||
throw new IllegalArgumentException("Unknown stream identifier " + streamIdentifer);
|
||||
}
|
||||
return stream;
|
||||
}
|
||||
|
||||
public synchronized Stream create(InputStream is, int blockSize) {
|
||||
idCounter++;
|
||||
Stream stream = new Stream(is, idCounter, blockSize);
|
||||
streams.put(stream.getId(), stream);
|
||||
|
||||
scheduleAbort(stream, System.currentTimeMillis() + TIME_OUT);
|
||||
return stream;
|
||||
}
|
||||
|
||||
public synchronized void destroy(Stream stream) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException e) {
|
||||
// OK
|
||||
}
|
||||
streams.remove(stream.getId());
|
||||
if (streams.isEmpty()) {
|
||||
timer.cancel();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void scheduleAbort(Stream s, long when) {
|
||||
if (timer == null) {
|
||||
timer = new Timer(true);
|
||||
}
|
||||
timer.schedule(new StreamCleanupTask(this, s), new Date(when + TIME_OUT));
|
||||
}
|
||||
}
|
||||
60
jdkSrc/jdk8/jdk/management/jfr/Stringifier.java
Normal file
60
jdkSrc/jdk8/jdk/management/jfr/Stringifier.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr;
|
||||
/**
|
||||
* Helper class for generating toString()
|
||||
*
|
||||
*/
|
||||
final class Stringifier {
|
||||
private final StringBuilder sb = new StringBuilder();
|
||||
private boolean first = true;
|
||||
|
||||
public void add(String name, Object value) {
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
sb.append(" ");
|
||||
}
|
||||
boolean isString = value instanceof String;
|
||||
sb.append(name).append("=");
|
||||
if (value == null) {
|
||||
sb.append("null");
|
||||
} else {
|
||||
if (isString) {
|
||||
sb.append("\"");
|
||||
}
|
||||
sb.append(value);
|
||||
if (isString) {
|
||||
sb.append("\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.management.jfr.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import jdk.jfr.internal.management.ManagementSupport;
|
||||
import jdk.management.jfr.FlightRecorderMXBean;
|
||||
import jdk.management.jfr.SettingDescriptorInfo;
|
||||
// XXX TODO
|
||||
//import sun.management.spi.PlatformMBeanProvider;
|
||||
|
||||
public final class FlightRecorderMXBeanProvider /*extends PlatformMBeanProvider */{
|
||||
|
||||
private final static class SingleMBeanComponent
|
||||
/*implements PlatformComponent<FlightRecorderMXBean>*/ {
|
||||
private final String objectName;
|
||||
private final Class<FlightRecorderMXBean> mbeanInterface;
|
||||
|
||||
public SingleMBeanComponent(String objectName,
|
||||
Class<FlightRecorderMXBean> mbeanInterface) {
|
||||
this.objectName = objectName;
|
||||
this.mbeanInterface = mbeanInterface;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public Set<String> mbeanInterfaceNames() {
|
||||
// return Collections.singleton(mbeanInterface.getName());
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Map<String, FlightRecorderMXBean> nameToMBeanMap() {
|
||||
// FlightRecorderMXBean bean = getFlightRecorderMXBean();
|
||||
// if (bean != null) {
|
||||
// return Collections.singletonMap(objectName, bean);
|
||||
// } else {
|
||||
// return Collections.emptyMap();
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public String getObjectNamePattern() {
|
||||
// return objectName;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Set<Class<? extends FlightRecorderMXBean>> mbeanInterfaces() {
|
||||
// return Collections.singleton(mbeanInterface);
|
||||
// }
|
||||
}
|
||||
|
||||
private static Callable<FlightRecorderMXBean> flightRecorderMXBeanFactory;
|
||||
|
||||
private static volatile FlightRecorderMXBean flightRecorderMXBean;
|
||||
|
||||
public static FlightRecorderMXBean getFlightRecorderMXBean() {
|
||||
FlightRecorderMXBean bean = flightRecorderMXBean;
|
||||
if (bean == null) {
|
||||
SettingDescriptorInfo.from(null); // Sets flightRecorderMXBeanFactory under <clinit> lock
|
||||
synchronized (flightRecorderMXBeanFactory) {
|
||||
bean = flightRecorderMXBean;
|
||||
if (bean != null) {
|
||||
return bean;
|
||||
}
|
||||
try {
|
||||
bean = flightRecorderMXBean = flightRecorderMXBeanFactory.call();
|
||||
} catch (Exception e) {
|
||||
ManagementSupport.logError("Could not create Flight Recorder "
|
||||
+ "instance for MBeanServer. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
public static void setFlightRecorderMXBeanFactory(Callable<FlightRecorderMXBean> factory) {
|
||||
flightRecorderMXBeanFactory = factory;
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public List<PlatformComponent<?>> getPlatformComponentList() {
|
||||
// String objectName = FlightRecorderMXBean.MXBEAN_NAME;
|
||||
// Class<FlightRecorderMXBean> mbeanInterface = FlightRecorderMXBean.class;
|
||||
// return Collections.singletonList(new SingleMBeanComponent(objectName, mbeanInterface));
|
||||
// }
|
||||
}
|
||||
Reference in New Issue
Block a user