1 /*
2 * Copyright (c) 2016, 2025, 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.Properties;
29
30 import jdk.internal.access.SharedSecrets;
31 import jdk.internal.event.JFRTracing;
32 import jdk.internal.event.ThrowableTracer;
33 import jdk.internal.platform.Container;
34 import jdk.internal.platform.Metrics;
35 import jdk.jfr.Event;
36 import jdk.jfr.events.ActiveRecordingEvent;
37 import jdk.jfr.events.ActiveSettingEvent;
38 import jdk.jfr.events.ContainerCPUThrottlingEvent;
39 import jdk.jfr.events.ContainerCPUUsageEvent;
40 import jdk.jfr.events.ContainerConfigurationEvent;
41 import jdk.jfr.events.ContainerIOUsageEvent;
42 import jdk.jfr.events.ContainerMemoryUsageEvent;
43 import jdk.jfr.events.DirectBufferStatisticsEvent;
44 import jdk.jfr.events.InitialSecurityPropertyEvent;
45 import jdk.jfr.events.MethodTimingEvent;
46 import jdk.jfr.events.MethodTraceEvent;
47 import jdk.jfr.internal.periodic.PeriodicEvents;
48 import jdk.jfr.internal.settings.MethodSetting;
49 import jdk.jfr.internal.tracing.PlatformTracer;
50 import jdk.jfr.tracing.MethodTracer;
51
52 public final class JDKEvents {
53
54 private static final Class<?>[] eventClasses = {
55 ActiveSettingEvent.class,
56 ActiveRecordingEvent.class,
57 // jdk.internal.event.* classes need their mirror
58 // event class to be listed in the MirrorEvents class.
59 jdk.internal.event.DeserializationEvent.class,
60 jdk.internal.event.ErrorThrownEvent.class,
61 jdk.internal.event.ExceptionStatisticsEvent.class,
62 jdk.internal.event.ExceptionThrownEvent.class,
63 jdk.internal.event.FileForceEvent.class,
64 jdk.internal.event.FileReadEvent.class,
65 jdk.internal.event.FileWriteEvent.class,
66 jdk.internal.event.ProcessStartEvent.class,
67 jdk.internal.event.SecurityPropertyModificationEvent.class,
68 jdk.internal.event.SecurityProviderServiceEvent.class,
69 jdk.internal.event.SerializationMisdeclarationEvent.class,
70 jdk.internal.event.SocketReadEvent.class,
71 jdk.internal.event.SocketWriteEvent.class,
72 jdk.internal.event.ThreadSleepEvent.class,
73 jdk.internal.event.TLSHandshakeEvent.class,
74 jdk.internal.event.VirtualThreadParkEvent.class,
75 jdk.internal.event.VirtualThreadStartEvent.class,
76 jdk.internal.event.VirtualThreadEndEvent.class,
77 jdk.internal.event.VirtualThreadSubmitFailedEvent.class,
78 jdk.internal.event.X509CertificateEvent.class,
79 jdk.internal.event.X509ValidationEvent.class,
80 DirectBufferStatisticsEvent.class,
81 InitialSecurityPropertyEvent.class,
82 MethodTraceEvent.class,
83 MethodTimingEvent.class,
84 };
85
86 private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
87 private static final Runnable emitDirectBufferStatistics = JDKEvents::emitDirectBufferStatistics;
88 private static final Runnable emitContainerConfiguration = JDKEvents::emitContainerConfiguration;
89 private static final Runnable emitContainerCPUUsage = JDKEvents::emitContainerCPUUsage;
90 private static final Runnable emitContainerCPUThrottling = JDKEvents::emitContainerCPUThrottling;
91 private static final Runnable emitContainerMemoryUsage = JDKEvents::emitContainerMemoryUsage;
92 private static final Runnable emitContainerIOUsage = JDKEvents::emitContainerIOUsage;
93 private static final Runnable emitInitialSecurityProperties = JDKEvents::emitInitialSecurityProperties;
94 private static final Runnable emitMethodTiming = JDKEvents::emitMethodTiming;
95 private static Metrics containerMetrics = null;
96 private static boolean initializationTriggered;
97
98 @SuppressWarnings("unchecked")
99 public static synchronized void initialize() {
100 try {
101 if (initializationTriggered == false) {
102 for (Class<?> eventClass : eventClasses) {
103 MetadataRepository.getInstance().register((Class<? extends Event>) eventClass);
104 }
105 PeriodicEvents.addJavaEvent(jdk.internal.event.ExceptionStatisticsEvent.class, emitExceptionStatistics);
106 PeriodicEvents.addJavaEvent(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics);
107 PeriodicEvents.addJavaEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties);
108 PeriodicEvents.addJavaEvent(MethodTimingEvent.class, emitMethodTiming);
109
110 initializeContainerEvents();
111 JFRTracing.enable();
112 initializationTriggered = true;
113 }
114 } catch (Exception e) {
115 Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage());
116 }
117 }
118
119 private static void initializeContainerEvents() {
120 if (JVM.isContainerized() ) {
121 Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "JVM is containerized");
122 containerMetrics = Container.metrics();
123 if (containerMetrics != null) {
124 Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "Container metrics are available");
125 }
126 }
127 // The registration of events and hooks are needed to provide metadata,
128 // even when not running in a container
129 registerEvent(ContainerConfigurationEvent.class);
130 registerEvent(ContainerCPUUsageEvent.class);
131 registerEvent(ContainerCPUThrottlingEvent.class);
132 registerEvent(ContainerMemoryUsageEvent.class);
133 registerEvent(ContainerIOUsageEvent.class);
134
135 PeriodicEvents.addJavaEvent(ContainerConfigurationEvent.class, emitContainerConfiguration);
136 PeriodicEvents.addJavaEvent(ContainerCPUUsageEvent.class, emitContainerCPUUsage);
137 PeriodicEvents.addJavaEvent(ContainerCPUThrottlingEvent.class, emitContainerCPUThrottling);
138 PeriodicEvents.addJavaEvent(ContainerMemoryUsageEvent.class, emitContainerMemoryUsage);
139 PeriodicEvents.addJavaEvent(ContainerIOUsageEvent.class, emitContainerIOUsage);
140 }
141
142 private static void registerEvent(Class<? extends jdk.internal.event.Event> eventClass) {
143 MetadataRepository.getInstance().register(eventClass);
144 }
145
146 private static void emitExceptionStatistics() {
147 ThrowableTracer.emitStatistics();
148 }
149
150 private static void emitContainerConfiguration() {
151 if (containerMetrics != null) {
152 ContainerConfigurationEvent t = new ContainerConfigurationEvent();
153 t.containerType = containerMetrics.getProvider();
154 t.cpuSlicePeriod = containerMetrics.getCpuPeriod();
155 t.cpuQuota = containerMetrics.getCpuQuota();
156 t.cpuShares = containerMetrics.getCpuShares();
157 t.effectiveCpuCount = containerMetrics.getEffectiveCpuCount();
158 t.memorySoftLimit = containerMetrics.getMemorySoftLimit();
159 t.memoryLimit = containerMetrics.getMemoryLimit();
160 t.swapMemoryLimit = containerMetrics.getMemoryAndSwapLimit();
161 t.hostTotalMemory = JVM.hostTotalMemory();
162 t.hostTotalSwapMemory = JVM.hostTotalSwapMemory();
163 t.commit();
164 }
165 }
166
167 private static void emitContainerCPUUsage() {
168 if (containerMetrics != null) {
169 ContainerCPUUsageEvent event = new ContainerCPUUsageEvent();
170
171 event.cpuTime = containerMetrics.getCpuUsage();
172 event.cpuSystemTime = containerMetrics.getCpuSystemUsage();
173 event.cpuUserTime = containerMetrics.getCpuUserUsage();
174 event.commit();
175 }
176 }
177 private static void emitContainerMemoryUsage() {
178 if (containerMetrics != null) {
179 ContainerMemoryUsageEvent event = new ContainerMemoryUsageEvent();
180
181 event.memoryFailCount = containerMetrics.getMemoryFailCount();
182 event.memoryUsage = containerMetrics.getMemoryUsage();
183 event.swapMemoryUsage = containerMetrics.getMemoryAndSwapUsage();
184 event.commit();
185 }
186 }
187
188 private static void emitContainerIOUsage() {
189 if (containerMetrics != null) {
190 ContainerIOUsageEvent event = new ContainerIOUsageEvent();
191
192 event.serviceRequests = containerMetrics.getBlkIOServiceCount();
193 event.dataTransferred = containerMetrics.getBlkIOServiced();
194 event.commit();
195 }
196 }
197
198 private static void emitContainerCPUThrottling() {
199 if (containerMetrics != null) {
200 ContainerCPUThrottlingEvent event = new ContainerCPUThrottlingEvent();
201
202 event.cpuElapsedSlices = containerMetrics.getCpuNumPeriods();
203 event.cpuThrottledSlices = containerMetrics.getCpuNumThrottled();
204 event.cpuThrottledTime = containerMetrics.getCpuThrottledTime();
205 event.commit();
206 }
207 }
208
209 public static void remove() {
210 PeriodicEvents.removeEvent(emitExceptionStatistics);
211 PeriodicEvents.removeEvent(emitDirectBufferStatistics);
212 PeriodicEvents.removeEvent(emitInitialSecurityProperties);
213 PeriodicEvents.removeEvent(emitMethodTiming);
214
215 PeriodicEvents.removeEvent(emitContainerConfiguration);
216 PeriodicEvents.removeEvent(emitContainerCPUUsage);
217 PeriodicEvents.removeEvent(emitContainerCPUThrottling);
218 PeriodicEvents.removeEvent(emitContainerMemoryUsage);
219 PeriodicEvents.removeEvent(emitContainerIOUsage);
220 }
221
222 private static void emitDirectBufferStatistics() {
223 DirectBufferStatisticsEvent e = new DirectBufferStatisticsEvent();
224 e.commit();
225 }
226
227 private static void emitInitialSecurityProperties() {
228 Properties p = SharedSecrets.getJavaSecurityPropertiesAccess().getInitialProperties();
229 if (p != null) {
230 for (String key : p.stringPropertyNames()) {
231 InitialSecurityPropertyEvent e = new InitialSecurityPropertyEvent();
232 e.key = key;
233 e.value = p.getProperty(key);
234 e.commit();
235 }
236 }
237 }
238
239 private static void emitMethodTiming() {
240 if (MethodSetting.isInitialized() && MethodTimingEvent.enabled()) {
241 PlatformTracer.emitTiming();
242 }
243 }
244 }