1 /* 2 * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.jfr.internal; 27 28 import java.util.ArrayList; 29 import java.util.List; 30 import java.util.Objects; 31 32 import jdk.jfr.SettingDescriptor; 33 34 /** 35 * Implementation of event type. 36 * 37 * To avoid memory leaks, this class must not hold strong reference to an event 38 * class or a setting class 39 */ 40 public final class PlatformEventType extends Type { 41 private final boolean isJVM; 42 private final boolean isJDK; 43 private final boolean isMethodSampling; 44 private final List<SettingDescriptor> settings = new ArrayList<>(5); 45 private final boolean dynamicSettings; 46 private final int stackTraceOffset; 47 48 // default values 49 private boolean largeSize = false; 50 private boolean enabled = false; 51 private boolean stackTraceEnabled = true; 52 private long thresholdTicks = 0; 53 private long period = 0; 54 private boolean hasHook; 55 56 private boolean beginChunk; 57 private boolean endChunk; 58 private boolean hasStackTrace = true; 59 private boolean hasDuration = true; 60 private boolean hasPeriod = true; 61 private boolean hasCutoff = false; 62 private boolean isInstrumented; 63 private boolean markForInstrumentation; 64 private boolean registered = true; 65 private boolean committable = enabled && registered; 66 67 68 // package private PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings)69 PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings) { 70 super(name, Type.SUPER_TYPE_EVENT, id); 71 this.dynamicSettings = dynamicSettings; 72 this.isJVM = Type.isDefinedByJVM(id); 73 this.isMethodSampling = isJVM && (name.equals(Type.EVENT_NAME_PREFIX + "ExecutionSample") || name.equals(Type.EVENT_NAME_PREFIX + "NativeMethodSample")); 74 this.isJDK = isJDK; 75 this.stackTraceOffset = stackTraceOffset(name, isJDK); 76 } 77 isExceptionEvent(String name)78 private static boolean isExceptionEvent(String name) { 79 switch (name) { 80 case Type.EVENT_NAME_PREFIX + "JavaErrorThrow" : 81 case Type.EVENT_NAME_PREFIX + "JavaExceptionThrow" : 82 return true; 83 } 84 return false; 85 } 86 isUsingHandler(String name)87 private static boolean isUsingHandler(String name) { 88 switch (name) { 89 case Type.EVENT_NAME_PREFIX + "SocketRead" : 90 case Type.EVENT_NAME_PREFIX + "SocketWrite" : 91 case Type.EVENT_NAME_PREFIX + "FileRead" : 92 case Type.EVENT_NAME_PREFIX + "FileWrite" : 93 case Type.EVENT_NAME_PREFIX + "FileForce" : 94 return true; 95 } 96 return false; 97 } 98 stackTraceOffset(String name, boolean isJDK)99 private static int stackTraceOffset(String name, boolean isJDK) { 100 if (isJDK) { 101 if (isExceptionEvent(name)) { 102 return 4; 103 } 104 if (isUsingHandler(name)) { 105 return 3; 106 } 107 } 108 return 4; 109 } 110 add(SettingDescriptor settingDescriptor)111 public void add(SettingDescriptor settingDescriptor) { 112 Objects.requireNonNull(settingDescriptor); 113 settings.add(settingDescriptor); 114 } 115 getSettings()116 public List<SettingDescriptor> getSettings() { 117 if (dynamicSettings) { 118 List<SettingDescriptor> list = new ArrayList<>(settings.size()); 119 for (SettingDescriptor s : settings) { 120 if (Utils.isSettingVisible(s.getTypeId(), hasHook)) { 121 list.add(s); 122 } 123 } 124 return list; 125 } 126 return settings; 127 } 128 getAllSettings()129 public List<SettingDescriptor> getAllSettings() { 130 return settings; 131 } 132 setHasStackTrace(boolean hasStackTrace)133 public void setHasStackTrace(boolean hasStackTrace) { 134 this.hasStackTrace = hasStackTrace; 135 } 136 setHasDuration(boolean hasDuration)137 public void setHasDuration(boolean hasDuration) { 138 this.hasDuration = hasDuration; 139 } 140 setHasCutoff(boolean hasCutoff)141 public void setHasCutoff(boolean hasCutoff) { 142 this.hasCutoff = hasCutoff; 143 } 144 setCutoff(long cutoffNanos)145 public void setCutoff(long cutoffNanos) { 146 if (isJVM) { 147 long cutoffTicks = Utils.nanosToTicks(cutoffNanos); 148 JVM.getJVM().setCutoff(getId(), cutoffTicks); 149 } 150 } 151 setHasPeriod(boolean hasPeriod)152 public void setHasPeriod(boolean hasPeriod) { 153 this.hasPeriod = hasPeriod; 154 } 155 hasStackTrace()156 public boolean hasStackTrace() { 157 return this.hasStackTrace; 158 } 159 hasDuration()160 public boolean hasDuration() { 161 return this.hasDuration; 162 } 163 hasPeriod()164 public boolean hasPeriod() { 165 return this.hasPeriod; 166 } 167 hasCutoff()168 public boolean hasCutoff() { 169 return this.hasCutoff; 170 } 171 isEnabled()172 public boolean isEnabled() { 173 return enabled; 174 } 175 isJVM()176 public boolean isJVM() { 177 return isJVM; 178 } 179 isJDK()180 public boolean isJDK() { 181 return isJDK; 182 } 183 setEnabled(boolean enabled)184 public void setEnabled(boolean enabled) { 185 this.enabled = enabled; 186 updateCommittable(); 187 if (isJVM) { 188 if (isMethodSampling) { 189 long p = enabled ? period : 0; 190 JVM.getJVM().setMethodSamplingInterval(getId(), p); 191 } else { 192 JVM.getJVM().setEnabled(getId(), enabled); 193 } 194 } 195 } 196 setPeriod(long periodMillis, boolean beginChunk, boolean endChunk)197 public void setPeriod(long periodMillis, boolean beginChunk, boolean endChunk) { 198 if (isMethodSampling) { 199 long p = enabled ? periodMillis : 0; 200 JVM.getJVM().setMethodSamplingInterval(getId(), p); 201 } 202 this.beginChunk = beginChunk; 203 this.endChunk = endChunk; 204 this.period = periodMillis; 205 } 206 setStackTraceEnabled(boolean stackTraceEnabled)207 public void setStackTraceEnabled(boolean stackTraceEnabled) { 208 this.stackTraceEnabled = stackTraceEnabled; 209 if (isJVM) { 210 JVM.getJVM().setStackTraceEnabled(getId(), stackTraceEnabled); 211 } 212 } 213 setThreshold(long thresholdNanos)214 public void setThreshold(long thresholdNanos) { 215 this.thresholdTicks = Utils.nanosToTicks(thresholdNanos); 216 if (isJVM) { 217 JVM.getJVM().setThreshold(getId(), thresholdTicks); 218 } 219 } 220 isEveryChunk()221 public boolean isEveryChunk() { 222 return period == 0; 223 } 224 getStackTraceEnabled()225 public boolean getStackTraceEnabled() { 226 return stackTraceEnabled; 227 } 228 getThresholdTicks()229 public long getThresholdTicks() { 230 return thresholdTicks; 231 } 232 getPeriod()233 public long getPeriod() { 234 return period; 235 } 236 hasEventHook()237 public boolean hasEventHook() { 238 return hasHook; 239 } 240 setEventHook(boolean hasHook)241 public void setEventHook(boolean hasHook) { 242 this.hasHook = hasHook; 243 } 244 isBeginChunk()245 public boolean isBeginChunk() { 246 return beginChunk; 247 } 248 isEndChunk()249 public boolean isEndChunk() { 250 return endChunk; 251 } 252 isInstrumented()253 public boolean isInstrumented() { 254 return isInstrumented; 255 } 256 setInstrumented()257 public void setInstrumented() { 258 isInstrumented = true; 259 } 260 markForInstrumentation(boolean markForInstrumentation)261 public void markForInstrumentation(boolean markForInstrumentation) { 262 this.markForInstrumentation = markForInstrumentation; 263 } 264 isMarkedForInstrumentation()265 public boolean isMarkedForInstrumentation() { 266 return markForInstrumentation; 267 } 268 setRegistered(boolean registered)269 public boolean setRegistered(boolean registered) { 270 if (this.registered != registered) { 271 this.registered = registered; 272 updateCommittable(); 273 LogTag logTag = isJVM() || isJDK() ? LogTag.JFR_SYSTEM_EVENT : LogTag.JFR_EVENT; 274 if (registered) { 275 Logger.log(logTag, LogLevel.INFO, "Registered " + getLogName()); 276 } else { 277 Logger.log(logTag, LogLevel.INFO, "Unregistered " + getLogName()); 278 } 279 if (!registered) { 280 MetadataRepository.getInstance().setUnregistered(); 281 } 282 return true; 283 } 284 return false; 285 } 286 updateCommittable()287 private void updateCommittable() { 288 this.committable = enabled && registered; 289 } 290 isRegistered()291 public final boolean isRegistered() { 292 return registered; 293 } 294 295 // Efficient check of enabled && registered isCommittable()296 public boolean isCommittable() { 297 return committable; 298 } 299 getStackTraceOffset()300 public int getStackTraceOffset() { 301 return stackTraceOffset; 302 } 303 isLargeSize()304 public boolean isLargeSize() { 305 return largeSize; 306 } 307 setLargeSize()308 public void setLargeSize() { 309 largeSize = true; 310 } 311 } 312