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 hasThrottle = false; 63 private boolean isInstrumented; 64 private boolean markForInstrumentation; 65 private boolean registered = true; 66 private boolean committable = enabled && registered; 67 68 69 // package private PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings)70 PlatformEventType(String name, long id, boolean isJDK, boolean dynamicSettings) { 71 super(name, Type.SUPER_TYPE_EVENT, id); 72 this.dynamicSettings = dynamicSettings; 73 this.isJVM = Type.isDefinedByJVM(id); 74 this.isMethodSampling = isJVM && (name.equals(Type.EVENT_NAME_PREFIX + "ExecutionSample") || name.equals(Type.EVENT_NAME_PREFIX + "NativeMethodSample")); 75 this.isJDK = isJDK; 76 this.stackTraceOffset = stackTraceOffset(name, isJDK); 77 } 78 isExceptionEvent(String name)79 private static boolean isExceptionEvent(String name) { 80 switch (name) { 81 case Type.EVENT_NAME_PREFIX + "JavaErrorThrow" : 82 case Type.EVENT_NAME_PREFIX + "JavaExceptionThrow" : 83 return true; 84 } 85 return false; 86 } 87 isUsingHandler(String name)88 private static boolean isUsingHandler(String name) { 89 switch (name) { 90 case Type.EVENT_NAME_PREFIX + "SocketRead" : 91 case Type.EVENT_NAME_PREFIX + "SocketWrite" : 92 case Type.EVENT_NAME_PREFIX + "FileRead" : 93 case Type.EVENT_NAME_PREFIX + "FileWrite" : 94 case Type.EVENT_NAME_PREFIX + "FileForce" : 95 return true; 96 } 97 return false; 98 } 99 stackTraceOffset(String name, boolean isJDK)100 private static int stackTraceOffset(String name, boolean isJDK) { 101 if (isJDK) { 102 if (isExceptionEvent(name)) { 103 return 4; 104 } 105 if (isUsingHandler(name)) { 106 return 3; 107 } 108 } 109 return 4; 110 } 111 add(SettingDescriptor settingDescriptor)112 public void add(SettingDescriptor settingDescriptor) { 113 Objects.requireNonNull(settingDescriptor); 114 settings.add(settingDescriptor); 115 } 116 getSettings()117 public List<SettingDescriptor> getSettings() { 118 if (dynamicSettings) { 119 List<SettingDescriptor> list = new ArrayList<>(settings.size()); 120 for (SettingDescriptor s : settings) { 121 if (Utils.isSettingVisible(s.getTypeId(), hasHook)) { 122 list.add(s); 123 } 124 } 125 return list; 126 } 127 return settings; 128 } 129 getAllSettings()130 public List<SettingDescriptor> getAllSettings() { 131 return settings; 132 } 133 setHasStackTrace(boolean hasStackTrace)134 public void setHasStackTrace(boolean hasStackTrace) { 135 this.hasStackTrace = hasStackTrace; 136 } 137 setHasDuration(boolean hasDuration)138 public void setHasDuration(boolean hasDuration) { 139 this.hasDuration = hasDuration; 140 } 141 setHasCutoff(boolean hasCutoff)142 public void setHasCutoff(boolean hasCutoff) { 143 this.hasCutoff = hasCutoff; 144 } 145 setHasThrottle(boolean hasThrottle)146 public void setHasThrottle(boolean hasThrottle) { 147 this.hasThrottle = hasThrottle; 148 } 149 setCutoff(long cutoffNanos)150 public void setCutoff(long cutoffNanos) { 151 if (isJVM) { 152 long cutoffTicks = Utils.nanosToTicks(cutoffNanos); 153 JVM.getJVM().setCutoff(getId(), cutoffTicks); 154 } 155 } 156 setThrottle(long eventSampleSize, long period_ms)157 public void setThrottle(long eventSampleSize, long period_ms) { 158 if (isJVM) { 159 JVM.getJVM().setThrottle(getId(), eventSampleSize, period_ms); 160 } 161 } 162 setHasPeriod(boolean hasPeriod)163 public void setHasPeriod(boolean hasPeriod) { 164 this.hasPeriod = hasPeriod; 165 } 166 hasStackTrace()167 public boolean hasStackTrace() { 168 return this.hasStackTrace; 169 } 170 hasDuration()171 public boolean hasDuration() { 172 return this.hasDuration; 173 } 174 hasPeriod()175 public boolean hasPeriod() { 176 return this.hasPeriod; 177 } 178 hasCutoff()179 public boolean hasCutoff() { 180 return this.hasCutoff; 181 } 182 hasThrottle()183 public boolean hasThrottle() { 184 return this.hasThrottle; 185 } 186 isEnabled()187 public boolean isEnabled() { 188 return enabled; 189 } 190 isJVM()191 public boolean isJVM() { 192 return isJVM; 193 } 194 isJDK()195 public boolean isJDK() { 196 return isJDK; 197 } 198 setEnabled(boolean enabled)199 public void setEnabled(boolean enabled) { 200 this.enabled = enabled; 201 updateCommittable(); 202 if (isJVM) { 203 if (isMethodSampling) { 204 long p = enabled ? period : 0; 205 JVM.getJVM().setMethodSamplingInterval(getId(), p); 206 } else { 207 JVM.getJVM().setEnabled(getId(), enabled); 208 } 209 } 210 } 211 setPeriod(long periodMillis, boolean beginChunk, boolean endChunk)212 public void setPeriod(long periodMillis, boolean beginChunk, boolean endChunk) { 213 if (isMethodSampling) { 214 long p = enabled ? periodMillis : 0; 215 JVM.getJVM().setMethodSamplingInterval(getId(), p); 216 } 217 this.beginChunk = beginChunk; 218 this.endChunk = endChunk; 219 this.period = periodMillis; 220 } 221 setStackTraceEnabled(boolean stackTraceEnabled)222 public void setStackTraceEnabled(boolean stackTraceEnabled) { 223 this.stackTraceEnabled = stackTraceEnabled; 224 if (isJVM) { 225 JVM.getJVM().setStackTraceEnabled(getId(), stackTraceEnabled); 226 } 227 } 228 setThreshold(long thresholdNanos)229 public void setThreshold(long thresholdNanos) { 230 this.thresholdTicks = Utils.nanosToTicks(thresholdNanos); 231 if (isJVM) { 232 JVM.getJVM().setThreshold(getId(), thresholdTicks); 233 } 234 } 235 isEveryChunk()236 public boolean isEveryChunk() { 237 return period == 0; 238 } 239 getStackTraceEnabled()240 public boolean getStackTraceEnabled() { 241 return stackTraceEnabled; 242 } 243 getThresholdTicks()244 public long getThresholdTicks() { 245 return thresholdTicks; 246 } 247 getPeriod()248 public long getPeriod() { 249 return period; 250 } 251 hasEventHook()252 public boolean hasEventHook() { 253 return hasHook; 254 } 255 setEventHook(boolean hasHook)256 public void setEventHook(boolean hasHook) { 257 this.hasHook = hasHook; 258 } 259 isBeginChunk()260 public boolean isBeginChunk() { 261 return beginChunk; 262 } 263 isEndChunk()264 public boolean isEndChunk() { 265 return endChunk; 266 } 267 isInstrumented()268 public boolean isInstrumented() { 269 return isInstrumented; 270 } 271 setInstrumented()272 public void setInstrumented() { 273 isInstrumented = true; 274 } 275 markForInstrumentation(boolean markForInstrumentation)276 public void markForInstrumentation(boolean markForInstrumentation) { 277 this.markForInstrumentation = markForInstrumentation; 278 } 279 isMarkedForInstrumentation()280 public boolean isMarkedForInstrumentation() { 281 return markForInstrumentation; 282 } 283 setRegistered(boolean registered)284 public boolean setRegistered(boolean registered) { 285 if (this.registered != registered) { 286 this.registered = registered; 287 updateCommittable(); 288 LogTag logTag = isJVM() || isJDK() ? LogTag.JFR_SYSTEM_EVENT : LogTag.JFR_EVENT; 289 if (registered) { 290 Logger.log(logTag, LogLevel.INFO, "Registered " + getLogName()); 291 } else { 292 Logger.log(logTag, LogLevel.INFO, "Unregistered " + getLogName()); 293 } 294 if (!registered) { 295 MetadataRepository.getInstance().setUnregistered(); 296 } 297 return true; 298 } 299 return false; 300 } 301 updateCommittable()302 private void updateCommittable() { 303 this.committable = enabled && registered; 304 } 305 isRegistered()306 public final boolean isRegistered() { 307 return registered; 308 } 309 310 // Efficient check of enabled && registered isCommittable()311 public boolean isCommittable() { 312 return committable; 313 } 314 getStackTraceOffset()315 public int getStackTraceOffset() { 316 return stackTraceOffset; 317 } 318 isLargeSize()319 public boolean isLargeSize() { 320 return largeSize; 321 } 322 setLargeSize()323 public void setLargeSize() { 324 largeSize = true; 325 } 326 } 327