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