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 jdk.internal.event.FinalFieldMutationEvent.class,
81 DirectBufferStatisticsEvent.class,
82 InitialSecurityPropertyEvent.class,
83 MethodTraceEvent.class,
84 MethodTimingEvent.class,
85 };
86
87 private static final Runnable emitExceptionStatistics = JDKEvents::emitExceptionStatistics;
88 private static final Runnable emitDirectBufferStatistics = JDKEvents::emitDirectBufferStatistics;
89 private static final Runnable emitContainerConfiguration = JDKEvents::emitContainerConfiguration;
90 private static final Runnable emitContainerCPUUsage = JDKEvents::emitContainerCPUUsage;
91 private static final Runnable emitContainerCPUThrottling = JDKEvents::emitContainerCPUThrottling;
92 private static final Runnable emitContainerMemoryUsage = JDKEvents::emitContainerMemoryUsage;
93 private static final Runnable emitContainerIOUsage = JDKEvents::emitContainerIOUsage;
94 private static final Runnable emitInitialSecurityProperties = JDKEvents::emitInitialSecurityProperties;
95 private static final Runnable emitMethodTiming = JDKEvents::emitMethodTiming;
96 private static Metrics containerMetrics = null;
97 private static boolean initializationTriggered;
98
99 @SuppressWarnings("unchecked")
100 public static synchronized void initialize() {
101 try {
102 if (initializationTriggered == false) {
103 for (Class<?> eventClass : eventClasses) {
104 MetadataRepository.getInstance().register((Class<? extends Event>) eventClass);
105 }
106 PeriodicEvents.addJavaEvent(jdk.internal.event.ExceptionStatisticsEvent.class, emitExceptionStatistics);
107 PeriodicEvents.addJavaEvent(DirectBufferStatisticsEvent.class, emitDirectBufferStatistics);
108 PeriodicEvents.addJavaEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties);
109 PeriodicEvents.addJavaEvent(MethodTimingEvent.class, emitMethodTiming);
110
111 initializeContainerEvents();
112 JFRTracing.enable();
113 initializationTriggered = true;
114 }
115 } catch (Exception e) {
116 Logger.log(LogTag.JFR_SYSTEM, LogLevel.WARN, "Could not initialize JDK events. " + e.getMessage());
117 }
118 }
119
120 private static void initializeContainerEvents() {
121 if (JVM.isContainerized() ) {
122 Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "JVM is containerized");
123 containerMetrics = Container.metrics();
124 if (containerMetrics != null) {
125 Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "Container metrics are available");
126 }
127 }
128 // The registration of events and hooks are needed to provide metadata,
129 // even when not running in a container
130 registerEvent(ContainerConfigurationEvent.class);
131 registerEvent(ContainerCPUUsageEvent.class);
132 registerEvent(ContainerCPUThrottlingEvent.class);
133 registerEvent(ContainerMemoryUsageEvent.class);
134 registerEvent(ContainerIOUsageEvent.class);
135
136 PeriodicEvents.addJavaEvent(ContainerConfigurationEvent.class, emitContainerConfiguration);
137 PeriodicEvents.addJavaEvent(ContainerCPUUsageEvent.class, emitContainerCPUUsage);
138 PeriodicEvents.addJavaEvent(ContainerCPUThrottlingEvent.class, emitContainerCPUThrottling);
139 PeriodicEvents.addJavaEvent(ContainerMemoryUsageEvent.class, emitContainerMemoryUsage);
140 PeriodicEvents.addJavaEvent(ContainerIOUsageEvent.class, emitContainerIOUsage);
141 }
142
143 private static void registerEvent(Class<? extends jdk.internal.event.Event> eventClass) {
144 MetadataRepository.getInstance().register(eventClass);
145 }
146
147 private static void emitExceptionStatistics() {
148 ThrowableTracer.emitStatistics();
149 }
150
151 private static void emitContainerConfiguration() {
152 if (containerMetrics != null) {
153 ContainerConfigurationEvent t = new ContainerConfigurationEvent();
154 t.containerType = containerMetrics.getProvider();
155 t.cpuSlicePeriod = containerMetrics.getCpuPeriod();
156 t.cpuQuota = containerMetrics.getCpuQuota();
157 t.cpuShares = containerMetrics.getCpuShares();
158 t.effectiveCpuCount = containerMetrics.getEffectiveCpuCount();
159 t.memorySoftLimit = containerMetrics.getMemorySoftLimit();
160 t.memoryLimit = containerMetrics.getMemoryLimit();
161 t.swapMemoryLimit = containerMetrics.getMemoryAndSwapLimit();
162 t.hostTotalMemory = JVM.hostTotalMemory();
163 t.hostTotalSwapMemory = JVM.hostTotalSwapMemory();
164 t.commit();
165 }
166 }
167
168 private static void emitContainerCPUUsage() {
169 if (containerMetrics != null) {
170 ContainerCPUUsageEvent event = new ContainerCPUUsageEvent();
171
172 event.cpuTime = containerMetrics.getCpuUsage();
173 event.cpuSystemTime = containerMetrics.getCpuSystemUsage();
174 event.cpuUserTime = containerMetrics.getCpuUserUsage();
175 event.commit();
176 }
177 }
178 private static void emitContainerMemoryUsage() {
179 if (containerMetrics != null) {
180 ContainerMemoryUsageEvent event = new ContainerMemoryUsageEvent();
181
182 event.memoryFailCount = containerMetrics.getMemoryFailCount();
183 event.memoryUsage = containerMetrics.getMemoryUsage();
184 event.swapMemoryUsage = containerMetrics.getMemoryAndSwapUsage();
185 event.commit();
186 }
187 }
188
189 private static void emitContainerIOUsage() {
190 if (containerMetrics != null) {
191 ContainerIOUsageEvent event = new ContainerIOUsageEvent();
192
193 event.serviceRequests = containerMetrics.getBlkIOServiceCount();
194 event.dataTransferred = containerMetrics.getBlkIOServiced();
195 event.commit();
196 }
197 }
198
199 private static void emitContainerCPUThrottling() {
200 if (containerMetrics != null) {
201 ContainerCPUThrottlingEvent event = new ContainerCPUThrottlingEvent();
202
203 event.cpuElapsedSlices = containerMetrics.getCpuNumPeriods();
204 event.cpuThrottledSlices = containerMetrics.getCpuNumThrottled();
205 event.cpuThrottledTime = containerMetrics.getCpuThrottledTime();
206 event.commit();
207 }
208 }
209
210 public static void remove() {
211 PeriodicEvents.removeEvent(emitExceptionStatistics);
212 PeriodicEvents.removeEvent(emitDirectBufferStatistics);
213 PeriodicEvents.removeEvent(emitInitialSecurityProperties);
214 PeriodicEvents.removeEvent(emitMethodTiming);
215
216 PeriodicEvents.removeEvent(emitContainerConfiguration);
217 PeriodicEvents.removeEvent(emitContainerCPUUsage);
218 PeriodicEvents.removeEvent(emitContainerCPUThrottling);
219 PeriodicEvents.removeEvent(emitContainerMemoryUsage);
220 PeriodicEvents.removeEvent(emitContainerIOUsage);
221 }
222
223 private static void emitDirectBufferStatistics() {
224 DirectBufferStatisticsEvent e = new DirectBufferStatisticsEvent();
225 e.commit();
226 }
227
228 private static void emitInitialSecurityProperties() {
229 Properties p = SharedSecrets.getJavaSecurityPropertiesAccess().getInitialProperties();
230 if (p != null) {
231 for (String key : p.stringPropertyNames()) {
232 InitialSecurityPropertyEvent e = new InitialSecurityPropertyEvent();
233 e.key = key;
234 e.value = p.getProperty(key);
235 e.commit();
236 }
237 }
238 }
239
240 private static void emitMethodTiming() {
241 if (MethodSetting.isInitialized() && MethodTimingEvent.enabled()) {
242 PlatformTracer.emitTiming();
243 }
244 }
245 }