diff --git a/src/java.base/share/classes/java/io/FileInputStream.java b/src/java.base/share/classes/java/io/FileInputStream.java index ab312fc8c5b..b5b4813cbb5 100644 --- a/src/java.base/share/classes/java/io/FileInputStream.java +++ b/src/java.base/share/classes/java/io/FileInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -205,22 +205,17 @@ public class FileInputStream extends InputStream private int traceRead0() throws IOException { int result = 0; - boolean endOfFile = false; long bytesRead = 0; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); result = read0(); if (result < 0) { - endOfFile = true; + bytesRead = -1; } else { bytesRead = 1; } } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - FileReadEvent.commit(start, duration, path, bytesRead, endOfFile); - } + FileReadEvent.offer(start, path, bytesRead); } return result; } @@ -236,19 +231,11 @@ public class FileInputStream extends InputStream private int traceReadBytes(byte b[], int off, int len) throws IOException { int bytesRead = 0; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); bytesRead = readBytes(b, off, len); } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } + FileReadEvent.offer(start, path, bytesRead); } return bytesRead; } diff --git a/src/java.base/share/classes/java/io/FileOutputStream.java b/src/java.base/share/classes/java/io/FileOutputStream.java index 6c5a30ea432..022aa44397a 100644 --- a/src/java.base/share/classes/java/io/FileOutputStream.java +++ b/src/java.base/share/classes/java/io/FileOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -266,16 +266,12 @@ public class FileOutputStream extends OutputStream private void traceWrite(int b, boolean append) throws IOException { long bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); write(b, append); bytesWritten = 1; } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } + FileWriteEvent.offer(start, path, bytesWritten); } } @@ -310,16 +306,12 @@ public class FileOutputStream extends OutputStream private void traceWriteBytes(byte b[], int off, int len, boolean append) throws IOException { long bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); writeBytes(b, off, len, append); bytesWritten = len; } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } + FileWriteEvent.offer(start, path, bytesWritten); } } diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java index c09f87afcdc..339030e022c 100644 --- a/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -367,21 +367,16 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private int traceRead0() throws IOException { int result = 0; long bytesRead = 0; - boolean endOfFile = false; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); result = read0(); if (result < 0) { - endOfFile = true; + bytesRead = -1; } else { bytesRead = 1; } } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - FileReadEvent.commit(start, duration, path, bytesRead, endOfFile); - } + FileReadEvent.offer(start, path, bytesRead); } return result; } @@ -404,19 +399,11 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private int traceReadBytes0(byte b[], int off, int len) throws IOException { int bytesRead = 0; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); bytesRead = readBytes0(b, off, len); } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } + FileReadEvent.offer(start, path, bytesRead); } return bytesRead; } @@ -582,16 +569,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private void traceImplWrite(int b) throws IOException { long bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); implWrite(b); bytesWritten = 1; } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } + FileWriteEvent.offer(start, path, bytesWritten); } } @@ -624,16 +607,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private void traceImplWriteBytes(byte b[], int off, int len) throws IOException { long bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); implWriteBytes(b, off, len); bytesWritten = len; } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } + FileWriteEvent.offer(start, path, bytesWritten); } } diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 8c0ce29dbee..ac3325fc514 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,7 +121,7 @@ public class Throwable implements Serializable { * Flag set by jdk.internal.event.JFRTracing to indicate if * exceptions should be traced by JFR. */ - static volatile boolean jfrTracing; + static boolean jfrTracing; /** * The JVM saves some indication of the stack backtrace in this slot. diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java index d2afa166a88..2905a51b402 100644 --- a/src/java.base/share/classes/java/net/Socket.java +++ b/src/java.base/share/classes/java/net/Socket.java @@ -965,10 +965,7 @@ public class Socket implements java.io.Closeable { } long start = SocketReadEvent.timestamp(); int nbytes = implRead(b, off, len); - long duration = SocketReadEvent.timestamp() - start; - if (SocketReadEvent.shouldCommit(duration)) { - SocketReadEvent.emit(start, duration, nbytes, parent.getRemoteSocketAddress(), getSoTimeout()); - } + SocketReadEvent.offer(start, nbytes, parent.getRemoteSocketAddress(), getSoTimeout()); return nbytes; } @@ -1081,10 +1078,7 @@ public class Socket implements java.io.Closeable { } long start = SocketWriteEvent.timestamp(); implWrite(b, off, len); - long duration = SocketWriteEvent.timestamp() - start; - if (SocketWriteEvent.shouldCommit(duration)) { - SocketWriteEvent.emit(start, duration, len, parent.getRemoteSocketAddress()); - } + SocketWriteEvent.offer(start, len, parent.getRemoteSocketAddress()); } private void implWrite(byte[] b, int off, int len) throws IOException { diff --git a/src/java.base/share/classes/jdk/internal/event/ExceptionThrownEvent.java b/src/java.base/share/classes/jdk/internal/event/ExceptionThrownEvent.java index 45c13e3010d..355ee81c0fc 100644 --- a/src/java.base/share/classes/jdk/internal/event/ExceptionThrownEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/ExceptionThrownEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,11 @@ public final class ExceptionThrownEvent extends Event { public String message; public Class> thrownClass; + public static boolean shouldThrottleCommit(long timestamp) { + // Generated by JFR + return false; + } + public static void commit(long start, String message, Class> thrownClass) { // Generated by JFR } diff --git a/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java b/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java index 34ff4e9d4ed..77b2568802e 100644 --- a/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,11 +45,33 @@ public final class FileReadEvent extends Event { return 0L; } - public static boolean shouldCommit(long duration) { + public static boolean shouldThrottleCommit(long duration, long end) { // Generated by JFR return false; } + /** + * Helper method to offer the data needed to potentially commit an event. + * The duration of the operation is computed using the current + * timestamp and the given start time. If the duration meets + * or exceeds the configured value and is not throttled (determined by calling the + * generated method {@link #shouldThrottleCommit(long, long)}), an event will be + * emitted by calling {@link #commit(long, long, String, long, boolean)} + * + * @param start the start time + * @param path the path + * @param bytesRead the number of bytes that were read, or -1 if the end of the file was reached + */ + public static void offer(long start, String path, long bytesRead) { + long end = timestamp(); + long duration = end - start; + if (shouldThrottleCommit(duration, end)) { + boolean endOfFile = bytesRead < 0; + long bytes = endOfFile ? 0 : bytesRead; + commit(start, duration, path, bytes, endOfFile); + } + } + public static void commit(long start, long duration, String path, long bytesRead, boolean endOfFile) { // Generated by JFR } diff --git a/src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java b/src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java index f6c27960430..3fa7dbe9822 100644 --- a/src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,11 +44,32 @@ public final class FileWriteEvent extends Event { return 0L; } - public static boolean shouldCommit(long duration) { + public static boolean shouldThrottleCommit(long duration, long end) { // Generated by JFR return false; } + /** + * Helper method to offer the data needed to potentially commit an event. + * The duration of the operation is computed using the current + * timestamp and the given start time. If the duration meets + * or exceeds the configured value and is not throttled (determined by calling the + * generated method {@link #shouldThrottleCommit(long, long)}), an event will be + * emitted by calling {@link #commit(long, long, String, long)} + * + * @param start the start time + * @param path the path + * @param bytesRead the number of bytes that were written, or -1 if the end of the file was reached + */ + public static void offer(long start, String path, long bytesWritten) { + long end = timestamp(); + long duration = end - start; + if (shouldThrottleCommit(duration, end)) { + long bytes = bytesWritten > 0 ? bytesWritten : 0; + commit(start, duration, path, bytes); + } + } + public static void commit(long start, long duration, String path, long bytesWritten) { // Generated by JFR } diff --git a/src/java.base/share/classes/jdk/internal/event/SocketReadEvent.java b/src/java.base/share/classes/jdk/internal/event/SocketReadEvent.java index d5f6c3241d9..09b3f23b07f 100644 --- a/src/java.base/share/classes/jdk/internal/event/SocketReadEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/SocketReadEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,9 +74,10 @@ public class SocketReadEvent extends Event { * of this method is generated automatically if jfr is enabled. * * @param duration time in nanoseconds to complete the operation + * @param end timestamp at the end of the operation * @return true if the event should be commited */ - public static boolean shouldCommit(long duration) { + public static boolean shouldThrottleCommit(long duration, long end) { // Generated by JFR return false; } @@ -118,8 +119,9 @@ public class SocketReadEvent extends Event { * @param timeout maximum time to wait */ public static void offer(long start, long nbytes, SocketAddress remote, long timeout) { - long duration = timestamp() - start; - if (shouldCommit(duration)) { + long end = timestamp(); + long duration = end - start; + if (shouldThrottleCommit(duration, end)) { emit(start, duration, nbytes, remote, timeout); } } diff --git a/src/java.base/share/classes/jdk/internal/event/SocketWriteEvent.java b/src/java.base/share/classes/jdk/internal/event/SocketWriteEvent.java index 7c56ef826a5..12d8ffbf65b 100644 --- a/src/java.base/share/classes/jdk/internal/event/SocketWriteEvent.java +++ b/src/java.base/share/classes/jdk/internal/event/SocketWriteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,10 +68,11 @@ public class SocketWriteEvent extends Event { * must exceed some threshold in order to commit the event. The implementation * of this method is generated automatically if jfr is enabled. * - * @param duration time in nanoseconds to complete the operation + * @param duration time to complete the operation + * @param end timestamp at the end of the operation * @return true if the event should be commited */ - public static boolean shouldCommit(long duration) { + public static boolean shouldThrottleCommit(long duration, long end) { // Generated by JFR return false; } @@ -104,7 +105,7 @@ public class SocketWriteEvent extends Event { * The duration of the operation is computed using the current * timestamp and the given start time. If the duration is meets * or exceeds the configured value (determined by calling the generated method - * {@link #shouldCommit(long)}), an event will be emitted by calling + * {@link #shouldThrottleCommit(long)}), an event will be emitted by calling * {@link #emit(long, long, long, SocketAddress)}. * * @param start the start time @@ -112,8 +113,9 @@ public class SocketWriteEvent extends Event { * @param remote the address of the remote socket being written to */ public static void offer(long start, long bytesWritten, SocketAddress remote) { - long duration = timestamp() - start; - if (shouldCommit(duration)) { + long end = timestamp(); + long duration = end - start; + if (shouldThrottleCommit(duration, end)) { emit(start, duration, bytesWritten, remote); } } diff --git a/src/java.base/share/classes/jdk/internal/event/ThrowableTracer.java b/src/java.base/share/classes/jdk/internal/event/ThrowableTracer.java index f7076b44e90..6502cbc8002 100644 --- a/src/java.base/share/classes/jdk/internal/event/ThrowableTracer.java +++ b/src/java.base/share/classes/jdk/internal/event/ThrowableTracer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,22 +37,24 @@ public final class ThrowableTracer { if (OutOfMemoryError.class.isAssignableFrom(clazz)) { return; } - - if (ErrorThrownEvent.enabled()) { + if (ErrorThrownEvent.enabled() || ExceptionThrownEvent.enabled()) { long timestamp = ErrorThrownEvent.timestamp(); - ErrorThrownEvent.commit(timestamp, message, clazz); - } - if (ExceptionThrownEvent.enabled()) { - long timestamp = ExceptionThrownEvent.timestamp(); - ExceptionThrownEvent.commit(timestamp, message, clazz); + if (ErrorThrownEvent.enabled()) { + ErrorThrownEvent.commit(timestamp, message, clazz); + } + if (ExceptionThrownEvent.shouldThrottleCommit(timestamp)) { + ExceptionThrownEvent.commit(timestamp, message, clazz); + } } numThrowables.incrementAndGet(); } public static void traceThrowable(Class> clazz, String message) { if (ExceptionThrownEvent.enabled()) { - long timestamp = ExceptionThrownEvent.timestamp(); - ExceptionThrownEvent.commit(timestamp, message, clazz); + long timestamp = ErrorThrownEvent.timestamp(); + if (ExceptionThrownEvent.shouldThrottleCommit(timestamp)) { + ExceptionThrownEvent.commit(timestamp, message, clazz); + } } numThrowables.incrementAndGet(); } diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index 72de217a83c..240405c2f7c 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -264,19 +264,11 @@ public class FileChannelImpl private int traceImplRead(ByteBuffer dst) throws IOException { int bytesRead = 0; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); bytesRead = implRead(dst); } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } + FileReadEvent.offer(start, path, bytesRead); } return bytesRead; } @@ -326,19 +318,11 @@ public class FileChannelImpl private long traceImplRead(ByteBuffer[] dsts, int offset, int length) throws IOException { long bytesRead = 0; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); bytesRead = implRead(dsts, offset, length); } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } + FileReadEvent.offer(start, path, bytesRead); } return bytesRead; } @@ -385,16 +369,11 @@ public class FileChannelImpl private int traceImplWrite(ByteBuffer src) throws IOException { int bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); bytesWritten = implWrite(src); } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - long bytes = bytesWritten > 0 ? bytesWritten : 0; - FileWriteEvent.commit(start, duration, path, bytes); - } + FileWriteEvent.offer(start, path, bytesWritten); } return bytesWritten; } @@ -441,16 +420,11 @@ public class FileChannelImpl private long traceImplWrite(ByteBuffer[] srcs, int offset, int length) throws IOException { long bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); bytesWritten = implWrite(srcs, offset, length); } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - long bytes = bytesWritten > 0 ? bytesWritten : 0; - FileWriteEvent.commit(start, duration, path, bytes); - } + FileWriteEvent.offer(start, path, bytesWritten); } return bytesWritten; } @@ -1199,19 +1173,11 @@ public class FileChannelImpl private int traceImplRead(ByteBuffer dst, long position) throws IOException { int bytesRead = 0; - long start = 0; + long start = FileReadEvent.timestamp(); try { - start = FileReadEvent.timestamp(); bytesRead = implRead(dst, position); } finally { - long duration = FileReadEvent.timestamp() - start; - if (FileReadEvent.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } + FileReadEvent.offer(start, path, bytesRead); } return bytesRead; } @@ -1271,16 +1237,11 @@ public class FileChannelImpl private int traceImplWrite(ByteBuffer src, long position) throws IOException { int bytesWritten = 0; - long start = 0; + long start = FileWriteEvent.timestamp(); try { - start = FileWriteEvent.timestamp(); bytesWritten = implWrite(src, position); } finally { - long duration = FileWriteEvent.timestamp() - start; - if (FileWriteEvent.shouldCommit(duration)) { - long bytes = bytesWritten > 0 ? bytesWritten : 0; - FileWriteEvent.commit(start, duration, path, bytes); - } + FileWriteEvent.offer(start, path, bytesWritten); } return bytesWritten; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/Throttle.java b/src/jdk.jfr/share/classes/jdk/jfr/Throttle.java similarity index 58% rename from src/jdk.jfr/share/classes/jdk/jfr/internal/Throttle.java rename to src/jdk.jfr/share/classes/jdk/jfr/Throttle.java index 39409d008ab..7b9771eba2b 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/Throttle.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Throttle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Datadog, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -24,7 +24,7 @@ * questions. */ -package jdk.jfr.internal; +package jdk.jfr; import java.lang.annotation.ElementType; import java.lang.annotation.Inherited; @@ -32,14 +32,15 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import jdk.jfr.MetadataDefinition; - /** - * Event annotation, determines the event emission rate in events per time unit. + * Event annotation, specifies the maximum rate of events per time unit, (for + * example, {@code "100/s"}). + *
+ * If the event class annotated with {@code Throttle} is filtered by other + * settings, such as a {@link jdk.jfr.Threshold} or a user-defined setting, the + * throttling will happen after those settings have been applied. * - * This setting is only supported for JVM events. - * - * @since 16 + * @since 25 */ @MetadataDefinition @Target({ ElementType.TYPE }) @@ -47,30 +48,33 @@ import jdk.jfr.MetadataDefinition; @Retention(RetentionPolicy.RUNTIME) public @interface Throttle { /** - * Settings name {@code "throttle"} for configuring an event emission rate in events per time unit. + * Setting name {@code "throttle"} for configuring throttled events. */ public static final String NAME = "throttle"; - public static final String DEFAULT = "off"; /** - * Throttle, for example {@code "100/s"}. + * The throttle rate, for example {@code "100/s"}. *
- * String representation of a non-negative {@code Long} value followed by a slash ("/")
- * and one of the following units
- * {@code "ns"} (nanoseconds)
- * {@code "us"} (microseconds)
- * {@code "ms"} (milliseconds)
- * {@code "s"} (seconds)
- * {@code "m"} (minutes)
- * {@code "h"} (hours)
- * {@code "d"} (days)
+ * String representation of a non-negative {@code long} value followed by a
+ * forward slash ("/") and one of the following units:
+ *
* Example values, {@code "6000/m"}, {@code "10/ms"} and {@code "200/s"}. - * When zero is specified, for example {@code "0/s"}, no events are emitted. - * When {@code "off"} is specified, all events are emitted. + *
+ * Specifying zero, for example {@code "0/s"}, results in no events being + * emitted. + *
+ * Specifying {@code "off"} (case-sensitive) results in all events being emitted.
*
* @return the throttle value, default {@code "off"} not {@code null}
- *
*/
- String value() default DEFAULT;
+ String value() default "off";
}
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java
index 22c87f3132d..41945aaf66c 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/ExceptionThrownEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@ import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Label;
import jdk.jfr.Name;
+import jdk.jfr.Throttle;
import jdk.jfr.internal.MirrorEvent;
import jdk.jfr.internal.RemoveFields;
import jdk.jfr.internal.Type;
@@ -38,6 +39,7 @@ import jdk.jfr.internal.Type;
@Category("Java Application")
@Description("An object derived from java.lang.Exception has been created")
@RemoveFields("duration")
+@Throttle
public final class ExceptionThrownEvent extends MirrorEvent {
@Label("Message")
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java
index 84886d2493a..bd9926c08d3 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@ import jdk.jfr.Description;
import jdk.jfr.Label;
import jdk.jfr.DataAmount;
import jdk.jfr.Name;
+import jdk.jfr.Throttle;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.MirrorEvent;
@@ -38,6 +39,7 @@ import jdk.jfr.internal.MirrorEvent;
@Category("Java Application")
@Description("Reading data from a file")
@StackFilter({"java.io.FileInputStream", "java.io.RandomAccessFile", "sun.nio.ch.FileChannelImpl"})
+@Throttle
public final class FileReadEvent extends MirrorEvent {
@Label("Path")
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java
index 990f1845168..e7861eef1b6 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@ import jdk.jfr.Description;
import jdk.jfr.Label;
import jdk.jfr.DataAmount;
import jdk.jfr.Name;
+import jdk.jfr.Throttle;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.MirrorEvent;
@@ -38,6 +39,7 @@ import jdk.jfr.internal.MirrorEvent;
@Category("Java Application")
@Description("Writing data to a file")
@StackFilter({"java.io.FileOutputStream", "java.io.RandomAccessFile", "sun.nio.ch.FileChannelImpl"})
+@Throttle
public final class FileWriteEvent extends MirrorEvent {
@Label("Path")
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/SocketReadEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/SocketReadEvent.java
index 917eabd9206..b2cdee4f8dc 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/SocketReadEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/SocketReadEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -31,6 +31,7 @@ import jdk.jfr.Label;
import jdk.jfr.DataAmount;
import jdk.jfr.Name;
import jdk.jfr.Timespan;
+import jdk.jfr.Throttle;
import jdk.jfr.internal.MirrorEvent;
import jdk.jfr.internal.Type;
@@ -38,6 +39,7 @@ import jdk.jfr.internal.Type;
@Label("Socket Read")
@Category("Java Application")
@Description("Reading data from a socket")
+@Throttle
public final class SocketReadEvent extends MirrorEvent {
@Label("Remote Host")
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/SocketWriteEvent.java b/src/jdk.jfr/share/classes/jdk/jfr/events/SocketWriteEvent.java
index 92c85c132d4..661a4d1a68e 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/events/SocketWriteEvent.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/events/SocketWriteEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@ import jdk.jfr.Description;
import jdk.jfr.Label;
import jdk.jfr.DataAmount;
import jdk.jfr.Name;
+import jdk.jfr.Throttle;
import jdk.jfr.internal.MirrorEvent;
import jdk.jfr.internal.Type;
@@ -37,6 +38,7 @@ import jdk.jfr.internal.Type;
@Label("Socket Write")
@Category("Java Application")
@Description("Writing data to a socket")
+@Throttle
public final class SocketWriteEvent extends MirrorEvent {
@Label("Remote Host")
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java
index d310c505da6..3646162e8f7 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/ClassInspector.java
@@ -51,6 +51,7 @@ import jdk.jfr.Name;
import jdk.jfr.Registered;
import jdk.jfr.SettingControl;
import jdk.jfr.SettingDefinition;
+import jdk.jfr.Throttle;
import jdk.jfr.internal.util.Bytecode;
import jdk.jfr.internal.util.ImplicitFields;
import jdk.jfr.internal.util.Bytecode.FieldDesc;
@@ -64,6 +65,7 @@ final class ClassInspector {
private static final ClassDesc ANNOTATION_NAME = classDesc(Name.class);
private static final ClassDesc ANNOTATION_ENABLED = classDesc(Enabled.class);
private static final ClassDesc ANNOTATION_REMOVE_FIELDS = classDesc(RemoveFields.class);
+ private static final ClassDesc ANNOTATION_THROTTLE = classDesc(Throttle.class);
private static final String[] EMPTY_STRING_ARRAY = {};
private final ClassModel classModel;
@@ -138,6 +140,20 @@ final class ClassInspector {
return true;
}
+ boolean isThrottled() {
+ String result = annotationValue(ANNOTATION_THROTTLE, String.class, "off");
+ if (result != null) {
+ return true;
+ }
+ if (superClass != null) {
+ Throttle t = superClass.getAnnotation(Throttle.class);
+ if (t != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
boolean hasStaticMethod(MethodDesc method) {
for (MethodModel m : classModel.methods()) {
if (Modifier.isStatic(m.flags().flagsMask())) {
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java
index 2ea4725abc8..02775b7707a 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventControl.java
@@ -44,6 +44,7 @@ import jdk.jfr.SettingControl;
import jdk.jfr.SettingDefinition;
import jdk.jfr.StackTrace;
import jdk.jfr.Threshold;
+import jdk.jfr.Throttle;
import jdk.jfr.events.ActiveSettingEvent;
import jdk.jfr.events.StackFilter;
import jdk.jfr.internal.settings.CutoffSetting;
@@ -55,6 +56,7 @@ import jdk.jfr.internal.settings.CPUThrottleSetting;
import jdk.jfr.internal.settings.StackTraceSetting;
import jdk.jfr.internal.settings.ThresholdSetting;
import jdk.jfr.internal.settings.ThrottleSetting;
+import jdk.jfr.internal.settings.Throttler;
import jdk.jfr.internal.tracing.Modification;
import jdk.jfr.internal.util.Utils;
@@ -95,6 +97,7 @@ public final class EventControl {
}
if (eventType.hasThrottle()) {
addControl(Throttle.NAME, defineThrottle(eventType));
+ eventType.setThrottler(new Throttler(eventType));
}
if (eventType.hasLevel()) {
addControl(Level.NAME, defineLevel(eventType));
diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
index 96e6f36e5c8..7f0ed76586a 100644
--- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
+++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java
@@ -60,7 +60,14 @@ import jdk.jfr.internal.util.ImplicitFields;
* Class responsible for adding instrumentation to a subclass of {@link Event}.
*
*/
-final class EventInstrumentation {
+public final class EventInstrumentation {
+ public static final long MASK_THROTTLE = 1 << 62;
+ public static final long MASK_THROTTLE_CHECK = 1 << 63;
+ public static final long MASK_THROTTLE_BITS = MASK_THROTTLE | MASK_THROTTLE_CHECK;
+ public static final long MASK_THROTTLE_CHECK_SUCCESS = MASK_THROTTLE_CHECK | MASK_THROTTLE;
+ public static final long MASK_THROTTLE_CHECK_FAIL = MASK_THROTTLE_CHECK | 0;
+ public static final long MASK_NON_THROTTLE_BITS = ~MASK_THROTTLE_BITS;
+
private static final FieldDesc FIELD_EVENT_CONFIGURATION = FieldDesc.of(Object.class, "eventConfiguration");
private static final ClassDesc TYPE_EVENT_CONFIGURATION = classDesc(EventConfiguration.class);
@@ -71,11 +78,17 @@ final class EventInstrumentation {
private static final MethodDesc METHOD_BEGIN = MethodDesc.of("begin", "()V");
private static final MethodDesc METHOD_COMMIT = MethodDesc.of("commit", "()V");
private static final MethodDesc METHOD_DURATION = MethodDesc.of("duration", "(J)J");
+ private static final MethodDesc METHOD_THROTTLE = MethodDesc.of("throttle", "(JJ)J");
private static final MethodDesc METHOD_ENABLED = MethodDesc.of("enabled", "()Z");
private static final MethodDesc METHOD_END = MethodDesc.of("end", "()V");
- private static final MethodDesc METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT = MethodDesc.of("shouldCommit", "(J)Z");
+ private static final MethodDesc METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT_LONG = MethodDesc.of("shouldCommit", "(J)Z");
+ private static final MethodDesc METHOD_EVENT_CONFIGURATION_SHOULD_THROTTLE_COMMIT_LONG_LONG = MethodDesc.of("shouldThrottleCommit", "(JJ)Z");
+ private static final MethodDesc METHOD_EVENT_CONFIGURATION_SHOULD_THROTTLE_COMMIT_LONG = MethodDesc.of("shouldThrottleCommit", "(J)Z");
+
private static final MethodDesc METHOD_EVENT_CONFIGURATION_GET_SETTING = MethodDesc.of("getSetting", SettingControl.class, int.class);
private static final MethodDesc METHOD_EVENT_SHOULD_COMMIT = MethodDesc.of("shouldCommit", "()Z");
+ private static final MethodDesc METHOD_EVENT_SHOULD_THROTTLE_COMMIT_LONG_LONG = MethodDesc.of("shouldThrottleCommit", "(JJ)Z");
+ private static final MethodDesc METHOD_EVENT_SHOULD_THROTTLE_COMMIT_LONG = MethodDesc.of("shouldThrottleCommit", "(J)Z");
private static final MethodDesc METHOD_GET_EVENT_WRITER = MethodDesc.of("getEventWriter", "()" + TYPE_EVENT_WRITER.descriptorString());
private static final MethodDesc METHOD_IS_ENABLED = MethodDesc.of("isEnabled", "()Z");
private static final MethodDesc METHOD_RESET = MethodDesc.of("reset", "()V");
@@ -88,6 +101,7 @@ final class EventInstrumentation {
private final MethodDesc staticCommitMethod;
private final boolean untypedEventConfiguration;
private final boolean guardEventConfiguration;
+ private final boolean throttled;
/**
* Creates an EventInstrumentation object.
@@ -110,6 +124,11 @@ final class EventInstrumentation {
this.eventClassDesc = inspector.getClassDesc();
this.staticCommitMethod = inspector.findStaticCommitMethod();
this.untypedEventConfiguration = hasUntypedConfiguration();
+ if (inspector.isJDK()) {
+ this.throttled = inspector.hasStaticMethod(METHOD_EVENT_SHOULD_THROTTLE_COMMIT_LONG_LONG);
+ } else {
+ this.throttled = inspector.isThrottled();
+ }
}
byte[] buildInstrumented() {
@@ -147,6 +166,12 @@ final class EventInstrumentation {
if (isMethod(method, METHOD_SHOULD_COMMIT_LONG)) {
return this::methodShouldCommitStatic;
}
+ if (isMethod(method, METHOD_EVENT_SHOULD_THROTTLE_COMMIT_LONG_LONG)) {
+ return this::methodShouldCommitThrottleStaticLongLong;
+ }
+ if (isMethod(method, METHOD_EVENT_SHOULD_THROTTLE_COMMIT_LONG)) {
+ return this::methodShouldCommitThrottleStaticLong;
+ }
if (isMethod(method, METHOD_TIME_STAMP)) {
return this::methodTimestamp;
}
@@ -188,11 +213,11 @@ final class EventInstrumentation {
if (!inspector.hasDuration()) {
throwMissingDuration(codeBuilder, "end");
} else {
- codeBuilder.aload(0);
- codeBuilder.aload(0);
- getfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME);
- invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_DURATION);
- putfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION);
+ setDuration(codeBuilder, cb -> {
+ codeBuilder.aload(0);
+ getfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_START_TIME);
+ invokestatic(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_DURATION);
+ });
codeBuilder.return_();
}
}
@@ -205,9 +230,8 @@ final class EventInstrumentation {
}
// if (!eventConfiguration.shouldCommit(duration) goto fail;
getEventConfiguration(codeBuilder);
- codeBuilder.aload(0);
- getfield(codeBuilder, eventClassDesc, ImplicitFields.FIELD_DURATION);
- invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT);
+ getDuration(codeBuilder);
+ invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_SHOULD_COMMIT_LONG);
codeBuilder.ifeq(fail);
List
+ *
+ * {@code throttle}
+ * Specifies the maximum rate of events per time unit.
+ * {@code "off"} (no throttling)
+ *
+ * "off", if events should not be throttled, otherwise a string representation of a positive {@code Long} value followed by forward slash ("/") and one of the following units:
+ *
+ *
+ *
+ *
+ * {@code "off"}
+ *
+ * {@code "100/s"}
+ * {@code "1000/m"}
+ *
* {@code filter}
* Specifies the filter for the event
* {@code ""} (empty string)
diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc
index 541d1d3aa2f..565dfbdee05 100644
--- a/src/jdk.jfr/share/conf/jfr/default.jfc
+++ b/src/jdk.jfr/share/conf/jfr/default.jfc
@@ -769,31 +769,35 @@