blob: de1300b8b54c6ba88615d31fc7a25b5a77205047 [file] [log] [blame]
/*
* Copyright (c) 2017, 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.jfr.internal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import jdk.jfr.SettingDescriptor;
/**
* Implementation of event type.
*
* To avoid memory leaks, this class must not hold strong reference to an event
* class or a setting class
*/
public final class PlatformEventType extends Type {
private final boolean isJVM;
private final boolean isJDK;
private final boolean isMethodSampling;
private final List<SettingDescriptor> settings = new ArrayList<>(5);
private final boolean dynamicSettings;
private final int stackTraceOffset;
// default values
private boolean enabled = false;
private boolean stackTraceEnabled = true;
private long thresholdTicks = 0;
private long period = 0;
private boolean hasHook;
private boolean beginChunk;
private boolean endChunk;
private boolean hasStackTrace = true;
private boolean hasDuration = true;
private boolean hasPeriod = true;
private boolean hasCutoff = false;
private boolean isInstrumented;
private boolean markForInstrumentation;
private boolean registered = true;
private boolean commitable = enabled && registered;
// package private
PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings) {
super(name, Type.SUPER_TYPE_EVENT, id);
this.dynamicSettings = dynamicSettings;
this.isJVM = Type.isDefinedByJVM(id);
this.isMethodSampling = isJVM && (name.equals(Type.EVENT_NAME_PREFIX + "ExecutionSample") || name.equals(Type.EVENT_NAME_PREFIX + "NativeMethodSample"));
this.isJDK = isJDK;
this.stackTraceOffset = stackTraceOffset(name, isJDK);
}
private static int stackTraceOffset(String name, boolean isJDK) {
if (isJDK) {
if (name.equals(Type.EVENT_NAME_PREFIX + "JavaExceptionThrow")) {
return 5;
}
if (name.equals(Type.EVENT_NAME_PREFIX + "JavaErrorThrow")) {
return 5;
}
}
return 4;
}
public void add(SettingDescriptor settingDescriptor) {
Objects.requireNonNull(settingDescriptor);
settings.add(settingDescriptor);
}
public List<SettingDescriptor> getSettings() {
if (dynamicSettings) {
List<SettingDescriptor> list = new ArrayList<>(settings.size());
for (SettingDescriptor s : settings) {
if (Utils.isSettingVisible(s.getTypeId(), hasHook)) {
list.add(s);
}
}
return list;
}
return settings;
}
public List<SettingDescriptor> getAllSettings() {
return settings;
}
public void setHasStackTrace(boolean hasStackTrace) {
this.hasStackTrace = hasStackTrace;
}
public void setHasDuration(boolean hasDuration) {
this.hasDuration = hasDuration;
}
public void setHasCutoff(boolean hasCutoff) {
this.hasCutoff = hasCutoff;
}
public void setCutoff(long cutoffNanos) {
if (isJVM) {
long cutoffTicks = Utils.nanosToTicks(cutoffNanos);
JVM.getJVM().setCutoff(getId(), cutoffTicks);
}
}
public void setHasPeriod(boolean hasPeriod) {
this.hasPeriod = hasPeriod;
}
public boolean hasStackTrace() {
return this.hasStackTrace;
}
public boolean hasDuration() {
return this.hasDuration;
}
public boolean hasPeriod() {
return this.hasPeriod;
}
public boolean hasCutoff() {
return this.hasCutoff;
}
public boolean isEnabled() {
return enabled;
}
public boolean isJVM() {
return isJVM;
}
public boolean isJDK() {
return isJDK;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
updateCommitable();
if (isJVM) {
if (isMethodSampling) {
long p = enabled ? period : 0;
JVM.getJVM().setMethodSamplingInterval(getId(), p);
} else {
JVM.getJVM().setEnabled(getId(), enabled);
}
}
}
public void setPeriod(long periodMillis, boolean beginChunk, boolean endChunk) {
if (isMethodSampling) {
long p = enabled ? periodMillis : 0;
JVM.getJVM().setMethodSamplingInterval(getId(), p);
}
this.beginChunk = beginChunk;
this.endChunk = endChunk;
this.period = periodMillis;
}
public void setStackTraceEnabled(boolean stackTraceEnabled) {
this.stackTraceEnabled = stackTraceEnabled;
if (isJVM) {
JVM.getJVM().setStackTraceEnabled(getId(), stackTraceEnabled);
}
}
public void setThreshold(long thresholdNanos) {
this.thresholdTicks = Utils.nanosToTicks(thresholdNanos);
if (isJVM) {
JVM.getJVM().setThreshold(getId(), thresholdTicks);
}
}
public boolean isEveryChunk() {
return period == 0;
}
public boolean getStackTraceEnabled() {
return stackTraceEnabled;
}
public long getThresholdTicks() {
return thresholdTicks;
}
public long getPeriod() {
return period;
}
public boolean hasEventHook() {
return hasHook;
}
public void setEventHook(boolean hasHook) {
this.hasHook = hasHook;
}
public boolean isBeginChunk() {
return beginChunk;
}
public boolean isEndChunk() {
return endChunk;
}
public boolean isInstrumented() {
return isInstrumented;
}
public void setInstrumented() {
isInstrumented = true;
}
public void markForInstrumentation(boolean markForInstrumentation) {
this.markForInstrumentation = markForInstrumentation;
}
public boolean isMarkedForInstrumentation() {
return markForInstrumentation;
}
public boolean setRegistered(boolean registered) {
if (this.registered != registered) {
this.registered = registered;
updateCommitable();
LogTag logTag = isJVM() || isJDK() ? LogTag.JFR_SYSTEM_EVENT : LogTag.JFR_EVENT;
if (registered) {
Logger.log(logTag, LogLevel.INFO, "Registered " + getLogName());
} else {
Logger.log(logTag, LogLevel.INFO, "Unregistered " + getLogName());
}
if (!registered) {
MetadataRepository.getInstance().setUnregistered();
}
return true;
}
return false;
}
private void updateCommitable() {
this.commitable = enabled && registered;
}
public final boolean isRegistered() {
return registered;
}
// Efficient check of enabled && registered
public boolean isCommitable() {
return commitable;
}
public int getStackTraceOffset() {
return stackTraceOffset;
}
}