From 4a20691e9b0276e2dc5e7eb6a4d05393d6b4c99c Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 30 May 2024 13:32:57 +0000 Subject: [PATCH] 8331876: JFR: Move file read and write events to java.base Reviewed-by: mgronlun, alanb --- .../classes/java/io/FileInputStream.java | 57 ++++++ .../classes/java/io/FileOutputStream.java | 49 +++++ .../classes/java/io/RandomAccessFile.java | 101 ++++++++++ .../share/classes/java/lang/Throwable.java | 3 +- .../jdk/internal/event/FileReadEvent.java | 56 ++++++ .../jdk/internal/event/FileWriteEvent.java} | 36 +++- .../jdk/internal/event/JFRTracing.java | 52 +++++ .../jdk/internal/event/ThrowableTracer.java | 9 +- .../classes/sun/nio/ch/FileChannelImpl.java | 159 ++++++++++++++- .../classes/jdk/jfr/events/FileReadEvent.java | 12 +- .../jdk/jfr/events/FileWriteEvent.java | 13 +- .../jdk/jfr/internal/MirrorEvents.java | 6 +- .../FileChannelImplInstrumentor.java | 183 ------------------ .../FileInputStreamInstrumentor.java | 119 ------------ .../FileOutputStreamInstrumentor.java | 107 ---------- .../jfr/internal/instrument/JDKEvents.java | 15 +- .../RandomAccessFileInstrumentor.java | 183 ------------------ ...ClassJFR.java => RedefineSharedClass.java} | 35 ++-- .../jfr/jvm/TestGetEventWriterPackage.java | 6 +- .../startupargs/TestRetransformUsingLog.java | 12 +- 20 files changed, 551 insertions(+), 662 deletions(-) create mode 100644 src/java.base/share/classes/jdk/internal/event/FileReadEvent.java rename src/{jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java => java.base/share/classes/jdk/internal/event/FileWriteEvent.java} (59%) create mode 100644 src/java.base/share/classes/jdk/internal/event/JFRTracing.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java delete mode 100644 src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java rename test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/{RedefineSharedClassJFR.java => RedefineSharedClass.java} (80%) diff --git a/src/java.base/share/classes/java/io/FileInputStream.java b/src/java.base/share/classes/java/io/FileInputStream.java index 1ed2eb05d37..20bf57a56c7 100644 --- a/src/java.base/share/classes/java/io/FileInputStream.java +++ b/src/java.base/share/classes/java/io/FileInputStream.java @@ -28,6 +28,7 @@ package java.io; import java.nio.channels.FileChannel; import java.util.Arrays; import jdk.internal.util.ArraysSupport; +import jdk.internal.event.FileReadEvent; import sun.nio.ch.FileChannelImpl; /** @@ -59,6 +60,12 @@ public class FileInputStream extends InputStream { private static final int DEFAULT_BUFFER_SIZE = 8192; + /** + * Flag set by jdk.internal.event.JFRTracing to indicate if + * file reads should be traced by JFR. + */ + private static boolean jfrTracing; + /* File Descriptor - handle to the open file */ private final FileDescriptor fd; @@ -222,11 +229,36 @@ public class FileInputStream extends InputStream */ @Override public int read() throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceRead0(); + } return read0(); } private native int read0() throws IOException; + private int traceRead0() throws IOException { + int result = 0; + boolean endOfFile = false; + long bytesRead = 0; + long start = 0; + try { + start = FileReadEvent.timestamp(); + result = read0(); + if (result < 0) { + endOfFile = true; + } else { + bytesRead = 1; + } + } finally { + long duration = FileReadEvent.timestamp() - start; + if (FileReadEvent.shouldCommit(duration)) { + FileReadEvent.commit(start, duration, path, bytesRead, endOfFile); + } + } + return result; + } + /** * Reads a subarray as a sequence of bytes. * @param b the data to be written @@ -236,6 +268,25 @@ public class FileInputStream extends InputStream */ private native int readBytes(byte[] b, int off, int len) throws IOException; + private int traceReadBytes(byte b[], int off, int len) throws IOException { + int bytesRead = 0; + long start = 0; + 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); + } + } + } + return bytesRead; + } + /** * Reads up to {@code b.length} bytes of data from this input * stream into an array of bytes. This method blocks until some input @@ -249,6 +300,9 @@ public class FileInputStream extends InputStream */ @Override public int read(byte[] b) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceReadBytes(b, 0, b.length); + } return readBytes(b, 0, b.length); } @@ -268,6 +322,9 @@ public class FileInputStream extends InputStream */ @Override public int read(byte[] b, int off, int len) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceReadBytes(b, off, len); + } return readBytes(b, off, len); } diff --git a/src/java.base/share/classes/java/io/FileOutputStream.java b/src/java.base/share/classes/java/io/FileOutputStream.java index 2b017080a11..b8c26f38143 100644 --- a/src/java.base/share/classes/java/io/FileOutputStream.java +++ b/src/java.base/share/classes/java/io/FileOutputStream.java @@ -28,6 +28,7 @@ package java.io; import java.nio.channels.FileChannel; import jdk.internal.access.SharedSecrets; import jdk.internal.access.JavaIOFileDescriptorAccess; +import jdk.internal.event.FileWriteEvent; import sun.nio.ch.FileChannelImpl; @@ -68,6 +69,12 @@ public class FileOutputStream extends OutputStream private static final JavaIOFileDescriptorAccess FD_ACCESS = SharedSecrets.getJavaIOFileDescriptorAccess(); + /** + * Flag set by jdk.internal.event.JFRTracing to indicate if + * file writes should be traced by JFR. + */ + private static boolean jfrTracing; + /** * The system dependent file descriptor. */ @@ -297,6 +304,21 @@ public class FileOutputStream extends OutputStream */ private native void write(int b, boolean append) throws IOException; + private void traceWrite(int b, boolean append) throws IOException { + long bytesWritten = 0; + long start = 0; + 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); + } + } + } + /** * Writes the specified byte to this file output stream. Implements * the {@code write} method of {@code OutputStream}. @@ -307,6 +329,10 @@ public class FileOutputStream extends OutputStream @Override public void write(int b) throws IOException { boolean append = FD_ACCESS.getAppend(fd); + if (jfrTracing && FileWriteEvent.enabled()) { + traceWrite(b, append); + return; + } write(b, append); } @@ -322,6 +348,21 @@ public class FileOutputStream extends OutputStream private native void writeBytes(byte[] b, int off, int len, boolean append) throws IOException; + private void traceWriteBytes(byte b[], int off, int len, boolean append) throws IOException { + long bytesWritten = 0; + long start = 0; + 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); + } + } + } + /** * Writes {@code b.length} bytes from the specified byte array * to this file output stream. @@ -332,6 +373,10 @@ public class FileOutputStream extends OutputStream @Override public void write(byte[] b) throws IOException { boolean append = FD_ACCESS.getAppend(fd); + if (jfrTracing && FileWriteEvent.enabled()) { + traceWriteBytes(b, 0, b.length, append); + return; + } writeBytes(b, 0, b.length, append); } @@ -348,6 +393,10 @@ public class FileOutputStream extends OutputStream @Override public void write(byte[] b, int off, int len) throws IOException { boolean append = FD_ACCESS.getAppend(fd); + if (jfrTracing && FileWriteEvent.enabled()) { + traceWriteBytes(b, off, len, append); + return; + } writeBytes(b, off, len, append); } diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java index ee7b90ea71a..d0dde87bdca 100644 --- a/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -31,6 +31,8 @@ import jdk.internal.access.JavaIORandomAccessFileAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Blocker; import jdk.internal.util.ByteArray; +import jdk.internal.event.FileReadEvent; +import jdk.internal.event.FileWriteEvent; import sun.nio.ch.FileChannelImpl; @@ -68,6 +70,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private static final int O_DSYNC = 8; private static final int O_TEMPORARY = 16; + /** + * Flag set by jdk.internal.event.JFRTracing to indicate if + * file reads and writes should be traced by JFR. + */ + private static boolean jfrTracing; + private final FileDescriptor fd; private final boolean rw; @@ -376,11 +384,36 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * end-of-file has been reached. */ public int read() throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceRead0(); + } return read0(); } private native int read0() throws IOException; + private int traceRead0() throws IOException { + int result = 0; + long bytesRead = 0; + boolean endOfFile = false; + long start = 0; + try { + start = FileReadEvent.timestamp(); + result = read0(); + if (result < 0) { + endOfFile = true; + } else { + bytesRead = 1; + } + } finally { + long duration = FileReadEvent.timestamp() - start; + if (FileReadEvent.shouldCommit(duration)) { + FileReadEvent.commit(start, duration, path, bytesRead, endOfFile); + } + } + return result; + } + /** * Reads a sub array as a sequence of bytes. * @param b the buffer into which the data is read. @@ -389,11 +422,33 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * @throws IOException If an I/O error has occurred. */ private int readBytes(byte[] b, int off, int len) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceReadBytes0(b, off, len); + } return readBytes0(b, off, len); } private native int readBytes0(byte[] b, int off, int len) throws IOException; + private int traceReadBytes0(byte b[], int off, int len) throws IOException { + int bytesRead = 0; + long start = 0; + 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); + } + } + } + return bytesRead; + } + /** * Reads up to {@code len} bytes of data from this file into an * array of bytes. This method blocks until at least one byte of input @@ -537,6 +592,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * @throws IOException if an I/O error occurs. */ public void write(int b) throws IOException { + if (jfrTracing && FileWriteEvent.enabled()) { + traceImplWrite(b); + return; + } + implWrite(b); + } + + private void implWrite(int b) throws IOException { boolean attempted = Blocker.begin(sync); try { write0(b); @@ -545,6 +608,21 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { } } + private void traceImplWrite(int b) throws IOException { + long bytesWritten = 0; + long start = 0; + try { + start = FileWriteEvent.timestamp(); + implWrite(b); + bytesWritten = 1; + } finally { + long duration = FileWriteEvent.timestamp() - start; + if (FileWriteEvent.shouldCommit(duration)) { + FileWriteEvent.commit(start, duration, path, bytesWritten); + } + } + } + private native void write0(int b) throws IOException; /** @@ -556,6 +634,14 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * @throws IOException If an I/O error has occurred. */ private void writeBytes(byte[] b, int off, int len) throws IOException { + if (jfrTracing && FileWriteEvent.enabled()) { + traceImplWriteBytes(b, off, len); + return; + } + implWriteBytes(b, off, len); + } + + private void implWriteBytes(byte[] b, int off, int len) throws IOException { boolean attempted = Blocker.begin(sync); try { writeBytes0(b, off, len); @@ -564,6 +650,21 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { } } + private void traceImplWriteBytes(byte b[], int off, int len) throws IOException { + long bytesWritten = 0; + long start = 0; + 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); + } + } + } + private native void writeBytes0(byte[] b, int off, int len) throws IOException; /** diff --git a/src/java.base/share/classes/java/lang/Throwable.java b/src/java.base/share/classes/java/lang/Throwable.java index 2e78dbc1c08..275961a9a9f 100644 --- a/src/java.base/share/classes/java/lang/Throwable.java +++ b/src/java.base/share/classes/java/lang/Throwable.java @@ -120,7 +120,8 @@ public class Throwable implements Serializable { private static final long serialVersionUID = -3042686055658047285L; /** - * Flag that determines if exceptions should be traced by JFR + * Flag set by jdk.internal.event.JFRTracing to indicate if + * exceptions should be traced by JFR. */ static volatile boolean jfrTracing; diff --git a/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java b/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java new file mode 100644 index 00000000000..34ff4e9d4ed --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/event/FileReadEvent.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.event; + +/** + * Event recording file reads. + */ +public final class FileReadEvent extends Event { + + // The order of these fields must be the same as the parameters in + // commit(..., String, long, boolean) + public String path; + public long bytesRead; + public boolean endOfFile; + + public static boolean enabled() { + // Generated by JFR + return false; + } + + public static long timestamp() { + // Generated by JFR + return 0L; + } + + public static boolean shouldCommit(long duration) { + // Generated by JFR + return false; + } + + public static void commit(long start, long duration, String path, long bytesRead, boolean endOfFile) { + // Generated by JFR + } +} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java b/src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java similarity index 59% rename from src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java rename to src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java index 7d829f69076..7a39f93b991 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java +++ b/src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -22,12 +22,34 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ +package jdk.internal.event; -package jdk.jfr.events; -import jdk.jfr.internal.JVMSupport; -import jdk.jfr.internal.event.EventConfiguration; +/** + * Event recording file writes. + */ +public final class FileWriteEvent extends Event { -public final class EventConfigurations { - public static final EventConfiguration FILE_READ = JVMSupport.getConfiguration(FileReadEvent.class); - public static final EventConfiguration FILE_WRITE = JVMSupport.getConfiguration(FileWriteEvent.class); + // The order of these fields must be the same as the parameters in + // commit(..., String, long) + public String path; + public long bytesWritten; + + public static boolean enabled() { + // Generated by JFR + return false; + } + + public static long timestamp() { + // Generated by JFR + return 0L; + } + + public static boolean shouldCommit(long duration) { + // Generated by JFR + return false; + } + + 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/JFRTracing.java b/src/java.base/share/classes/jdk/internal/event/JFRTracing.java new file mode 100644 index 00000000000..5882b2ddc88 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/event/JFRTracing.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.internal.event; + +import sun.nio.ch.FileChannelImpl; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.RandomAccessFile; +import java.lang.Throwable; +import java.lang.reflect.Field; + +/** + * Helper class to enable JFR tracing. + */ +public final class JFRTracing { + + public static void enable() throws NoSuchFieldException, IllegalAccessException { + enable(Throwable.class); + enable(FileInputStream.class); + enable(FileOutputStream.class); + enable(FileChannelImpl.class); + enable(RandomAccessFile.class); + } + + private static void enable(Class clazz) throws NoSuchFieldException, IllegalAccessException { + Field field = clazz.getDeclaredField("jfrTracing"); + field.setAccessible(true); + field.setBoolean(null, true); + } +} 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 151312f111f..f7076b44e90 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, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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 @@ -24,7 +24,6 @@ */ package jdk.internal.event; -import java.lang.reflect.Field; import java.util.concurrent.atomic.AtomicLong; /** @@ -34,12 +33,6 @@ public final class ThrowableTracer { private static final AtomicLong numThrowables = new AtomicLong(); - public static void enable() throws NoSuchFieldException, IllegalAccessException { - Field field = Throwable.class.getDeclaredField("jfrTracing"); - field.setAccessible(true); - field.setBoolean(null, true); - } - public static void traceError(Class clazz, String message) { if (OutOfMemoryError.class.isAssignableFrom(clazz)) { return; 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 0b72ee6a7c2..f65a3900740 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -60,7 +60,8 @@ import jdk.internal.misc.VM; import jdk.internal.misc.VM.BufferPool; import jdk.internal.ref.Cleaner; import jdk.internal.ref.CleanerFactory; - +import jdk.internal.event.FileReadEvent; +import jdk.internal.event.FileWriteEvent; import jdk.internal.access.foreign.UnmapperProxy; public class FileChannelImpl @@ -73,6 +74,10 @@ public class FileChannelImpl // Used to make native read and write calls private static final FileDispatcher nd = new FileDispatcherImpl(); + // Flag set by jdk.internal.event.JFRTracing to indicate if + // file reads and writes should be traced by JFR. + private static boolean jfrTracing; + // File descriptor private final FileDescriptor fd; @@ -220,6 +225,13 @@ public class FileChannelImpl @Override public int read(ByteBuffer dst) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceImplRead(dst); + } + return implRead(dst); + } + + private int implRead(ByteBuffer dst) throws IOException { ensureOpen(); if (!readable) throw new NonReadableChannelException(); @@ -250,8 +262,34 @@ public class FileChannelImpl } } + private int traceImplRead(ByteBuffer dst) throws IOException { + int bytesRead = 0; + long start = 0; + 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); + } + } + } + return bytesRead; + } + @Override - public long read(ByteBuffer[] dsts, int offset, int length) + public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceImplRead(dsts, offset, length); + } + return implRead(dsts, offset, length); + } + + private long implRead(ByteBuffer[] dsts, int offset, int length) throws IOException { Objects.checkFromIndexSize(offset, length, dsts.length); @@ -286,8 +324,34 @@ public class FileChannelImpl } } + private long traceImplRead(ByteBuffer[] dsts, int offset, int length) throws IOException { + long bytesRead = 0; + long start = 0; + 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); + } + } + } + return bytesRead; + } + @Override public int write(ByteBuffer src) throws IOException { + if (jfrTracing && FileWriteEvent.enabled()) { + return traceImplWrite(src); + } + return implWrite(src); + } + + private int implWrite(ByteBuffer src) throws IOException { ensureOpen(); if (!writable) throw new NonWritableChannelException(); @@ -319,10 +383,31 @@ public class FileChannelImpl } } + private int traceImplWrite(ByteBuffer src) throws IOException { + int bytesWritten = 0; + long start = 0; + 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); + } + } + return bytesWritten; + } + @Override - public long write(ByteBuffer[] srcs, int offset, int length) - throws IOException - { + public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { + if (jfrTracing && FileWriteEvent.enabled()) { + return traceImplWrite(srcs, offset, length); + } + return implWrite(srcs, offset, length); + } + + private long implWrite(ByteBuffer[] srcs, int offset, int length) throws IOException { Objects.checkFromIndexSize(offset, length, srcs.length); ensureOpen(); if (!writable) @@ -354,6 +439,21 @@ public class FileChannelImpl } } + private long traceImplWrite(ByteBuffer[] srcs, int offset, int length) throws IOException { + long bytesWritten = 0; + long start = 0; + 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); + } + } + return bytesWritten; + } // -- Other operations -- @Override @@ -1028,6 +1128,13 @@ public class FileChannelImpl @Override public int read(ByteBuffer dst, long position) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceImplRead(dst, position); + } + return implRead(dst, position); + } + + private int implRead(ByteBuffer dst, long position) throws IOException { if (dst == null) throw new NullPointerException(); if (position < 0) @@ -1046,6 +1153,25 @@ public class FileChannelImpl } } + private int traceImplRead(ByteBuffer dst, long position) throws IOException { + int bytesRead = 0; + long start = 0; + 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); + } + } + } + return bytesRead; + } + private int readInternal(ByteBuffer dst, long position) throws IOException { assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); int n = 0; @@ -1074,6 +1200,13 @@ public class FileChannelImpl @Override public int write(ByteBuffer src, long position) throws IOException { + if (jfrTracing && FileReadEvent.enabled()) { + return traceImplWrite(src, position); + } + return implWrite(src, position); + } + + private int implWrite(ByteBuffer src, long position) throws IOException { if (src == null) throw new NullPointerException(); if (position < 0) @@ -1092,6 +1225,22 @@ public class FileChannelImpl } } + private int traceImplWrite(ByteBuffer src, long position) throws IOException { + int bytesWritten = 0; + long start = 0; + 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); + } + } + return bytesWritten; + } + private int writeInternal(ByteBuffer src, long position) throws IOException { assert !nd.needsPositionLock() || Thread.holdsLock(positionLock); int n = 0; 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 76daa39b571..84886d2493a 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, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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,15 +31,14 @@ import jdk.jfr.Label; import jdk.jfr.DataAmount; import jdk.jfr.Name; import jdk.jfr.internal.Type; +import jdk.jfr.internal.MirrorEvent; @Name(Type.EVENT_NAME_PREFIX + "FileRead") @Label("File Read") @Category("Java Application") @Description("Reading data from a file") -public final class FileReadEvent extends AbstractJDKEvent { - - // The order of these fields must be the same as the parameters in - // commit(..., String, long, boolean) +@StackFilter({"java.io.FileInputStream", "java.io.RandomAccessFile", "sun.nio.ch.FileChannelImpl"}) +public final class FileReadEvent extends MirrorEvent { @Label("Path") @Description("Full path of the file, or N/A if a file descriptor was used to create the stream, for example System.in") @@ -54,7 +53,4 @@ public final class FileReadEvent extends AbstractJDKEvent { @Description("If end of file was reached") public boolean endOfFile; - public static void commit(long start, long duration, String path, long bytesRead, boolean endOfFile) { - // Generated - } } 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 508c4eb07cc..990f1845168 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, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, 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,15 +31,14 @@ import jdk.jfr.Label; import jdk.jfr.DataAmount; import jdk.jfr.Name; import jdk.jfr.internal.Type; +import jdk.jfr.internal.MirrorEvent; @Name(Type.EVENT_NAME_PREFIX + "FileWrite") @Label("File Write") @Category("Java Application") @Description("Writing data to a file") -public final class FileWriteEvent extends AbstractJDKEvent { - - // The order of these fields must be the same as the parameters in - // commit(..., String, long) +@StackFilter({"java.io.FileOutputStream", "java.io.RandomAccessFile", "sun.nio.ch.FileChannelImpl"}) +public final class FileWriteEvent extends MirrorEvent { @Label("Path") @Description("Full path of the file, or N/A if a file descriptor was used to create the stream, for example System.out and System.err") @@ -49,8 +48,4 @@ public final class FileWriteEvent extends AbstractJDKEvent { @Description("Number of bytes written to the file") @DataAmount public long bytesWritten; - - public static void commit(long start, long duration, String path, long bytesWritten) { - // Generated - } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java index 8ae1f3b031f..35eadff40d1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -32,6 +32,8 @@ import jdk.jfr.events.ErrorThrownEvent; import jdk.jfr.events.ExceptionStatisticsEvent; import jdk.jfr.events.ExceptionThrownEvent; import jdk.jfr.events.FileForceEvent; +import jdk.jfr.events.FileReadEvent; +import jdk.jfr.events.FileWriteEvent; import jdk.jfr.events.ProcessStartEvent; import jdk.jfr.events.SecurityPropertyModificationEvent; import jdk.jfr.events.SecurityProviderServiceEvent; @@ -57,6 +59,8 @@ final class MirrorEvents { static { register("jdk.internal.event.DeserializationEvent", DeserializationEvent.class); register("jdk.internal.event.FileForceEvent", FileForceEvent.class); + register("jdk.internal.event.FileReadEvent", FileReadEvent.class); + register("jdk.internal.event.FileWriteEvent", FileWriteEvent.class); register("jdk.internal.event.ProcessStartEvent", ProcessStartEvent.class); register("jdk.internal.event.SecurityPropertyModificationEvent", SecurityPropertyModificationEvent.class); register("jdk.internal.event.SecurityProviderServiceEvent", SecurityProviderServiceEvent.class); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java deleted file mode 100644 index 5a795395c72..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2013, 2024, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jfr.internal.instrument; - -import java.io.IOException; -import java.nio.ByteBuffer; - -import jdk.jfr.events.FileForceEvent; -import jdk.jfr.events.FileReadEvent; -import jdk.jfr.events.FileWriteEvent; -import jdk.jfr.internal.event.EventConfiguration; -import jdk.jfr.events.EventConfigurations; - -/** - * See {@link JITracer} for an explanation of this code. - */ -@JIInstrumentationTarget("sun.nio.ch.FileChannelImpl") -final class FileChannelImplInstrumentor { - - private FileChannelImplInstrumentor() { - } - - private String path; - - @JIInstrumentationMethod - public int read(ByteBuffer dst) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(dst); - } - int bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(dst); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } - - @JIInstrumentationMethod - public int read(ByteBuffer dst, long position) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(dst, position); - } - int bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(dst, position); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } - - @JIInstrumentationMethod - public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(dsts, offset, length); - } - long bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(dsts, offset, length); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } - - @JIInstrumentationMethod - public int write(ByteBuffer src) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - return write(src); - } - int bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesWritten = write(src); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - long bytes = bytesWritten > 0 ? bytesWritten : 0; - FileWriteEvent.commit(start, duration, path, bytes); - } - } - return bytesWritten; - } - - @JIInstrumentationMethod - public int write(ByteBuffer src, long position) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - return write(src, position); - } - - int bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesWritten = write(src, position); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - long bytes = bytesWritten > 0 ? bytesWritten : 0; - FileWriteEvent.commit(start, duration, path, bytes); - } - } - return bytesWritten; - } - - @JIInstrumentationMethod - public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - return write(srcs, offset, length); - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesWritten = write(srcs, offset, length); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - long bytes = bytesWritten > 0 ? bytesWritten : 0; - FileWriteEvent.commit(start, duration, path, bytes); - } - } - return bytesWritten; - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java deleted file mode 100644 index 1d1ccb3bcb2..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2013, 2022, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jfr.internal.instrument; - -import java.io.IOException; - -import jdk.jfr.events.EventConfigurations; -import jdk.jfr.events.FileReadEvent; -import jdk.jfr.internal.event.EventConfiguration; - -/** - * See {@link JITracer} for an explanation of this code. - */ -@JIInstrumentationTarget("java.io.FileInputStream") -final class FileInputStreamInstrumentor { - - private FileInputStreamInstrumentor() { - } - - private String path; - - @JIInstrumentationMethod - public int read() throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(); - } - int result = 0; - boolean endOfFile = false; - long bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - result = read(); - if (result < 0) { - endOfFile = true; - } else { - bytesRead = 1; - } - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileReadEvent.commit(start, duration, path, bytesRead, endOfFile); - } - } - return result; - } - - @JIInstrumentationMethod - public int read(byte b[]) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(b); - } - int bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(b); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } - - @JIInstrumentationMethod - public int read(byte b[], int off, int len) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(b, off, len); - } - int bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(b, off, len); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java deleted file mode 100644 index 2e9e750df9d..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2013, 2022, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jfr.internal.instrument; - -import java.io.IOException; - -import jdk.jfr.events.FileWriteEvent; -import jdk.jfr.internal.event.EventConfiguration; -import jdk.jfr.events.EventConfigurations; - -/** - * See {@link JITracer} for an explanation of this code. - */ -@JIInstrumentationTarget("java.io.FileOutputStream") -final class FileOutputStreamInstrumentor { - - private FileOutputStreamInstrumentor() { - } - - private String path; - - @JIInstrumentationMethod - public void write(int b) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - write(b); - return; - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - write(b); - bytesWritten = 1; - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } - } - } - - @JIInstrumentationMethod - public void write(byte b[]) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - write(b); - return; - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - write(b); - bytesWritten = b.length; - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } - } - } - - @JIInstrumentationMethod - public void write(byte b[], int off, int len) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - write(b, off, len); - return; - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - write(b, off, len); - bytesWritten = len; - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } - } - } -} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java index fb981c42cae..09f811b6a0f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 java.util.List; import java.util.Properties; import jdk.internal.access.SharedSecrets; +import jdk.internal.event.JFRTracing; import jdk.internal.event.ThrowableTracer; import jdk.jfr.Event; import jdk.jfr.events.ActiveRecordingEvent; @@ -41,8 +42,6 @@ import jdk.jfr.events.ContainerCPUThrottlingEvent; import jdk.jfr.events.ContainerMemoryUsageEvent; import jdk.jfr.events.DirectBufferStatisticsEvent; import jdk.jfr.events.FileForceEvent; -import jdk.jfr.events.FileReadEvent; -import jdk.jfr.events.FileWriteEvent; import jdk.jfr.events.InitialSecurityPropertyEvent; import jdk.jfr.internal.JVM; @@ -57,8 +56,6 @@ import jdk.internal.platform.Metrics; public final class JDKEvents { private static final Class[] eventClasses = { - FileReadEvent.class, - FileWriteEvent.class, ActiveSettingEvent.class, ActiveRecordingEvent.class, // jdk.internal.event.* classes need their mirror @@ -68,6 +65,8 @@ public final class JDKEvents { jdk.internal.event.ExceptionStatisticsEvent.class, jdk.internal.event.ExceptionThrownEvent.class, jdk.internal.event.FileForceEvent.class, + jdk.internal.event.FileReadEvent.class, + jdk.internal.event.FileWriteEvent.class, jdk.internal.event.ProcessStartEvent.class, jdk.internal.event.SecurityPropertyModificationEvent.class, jdk.internal.event.SecurityProviderServiceEvent.class, @@ -88,10 +87,6 @@ public final class JDKEvents { // This is a list of the classes with instrumentation code that should be applied. private static final Class[] instrumentationClasses = new Class[] { - FileInputStreamInstrumentor.class, - FileOutputStreamInstrumentor.class, - RandomAccessFileInstrumentor.class, - FileChannelImplInstrumentor.class }; private static final Class[] targetClasses = new Class[instrumentationClasses.length]; @@ -118,7 +113,7 @@ public final class JDKEvents { PeriodicEvents.addJDKEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties); initializeContainerEvents(); - ThrowableTracer.enable(); + JFRTracing.enable(); initializationTriggered = true; } } catch (Exception e) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java deleted file mode 100644 index 128859358d8..00000000000 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (c) 2013, 2022, 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package jdk.jfr.internal.instrument; - -import java.io.IOException; - -import jdk.jfr.events.FileReadEvent; -import jdk.jfr.events.FileWriteEvent; -import jdk.jfr.internal.event.EventConfiguration; -import jdk.jfr.events.EventConfigurations; - -/** - * See {@link JITracer} for an explanation of this code. - */ -@JIInstrumentationTarget("java.io.RandomAccessFile") -final class RandomAccessFileInstrumentor { - - private RandomAccessFileInstrumentor() { - } - - private String path; - - @JIInstrumentationMethod - public int read() throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(); - } - int result = 0; - long bytesRead = 0; - boolean endOfFile = false; - long start = 0; - try { - start = EventConfiguration.timestamp(); - result = read(); - if (result < 0) { - endOfFile = true; - } else { - bytesRead = 1; - } - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileReadEvent.commit(start, duration, path, bytesRead, endOfFile); - } - } - return result; - } - - @JIInstrumentationMethod - public int read(byte b[]) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(b); - } - int bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(b); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } - - @JIInstrumentationMethod - public int read(byte b[], int off, int len) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_READ; - if (!eventConfiguration.isEnabled()) { - return read(b, off, len); - } - int bytesRead = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - bytesRead = read(b, off, len); - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - if (bytesRead < 0) { - FileReadEvent.commit(start, duration, path, 0L, true); - } else { - FileReadEvent.commit(start, duration, path, bytesRead, false); - } - } - } - return bytesRead; - } - - @JIInstrumentationMethod - public void write(int b) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - write(b); - return; - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - write(b); - bytesWritten = 1; - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } - } - } - - @JIInstrumentationMethod - public void write(byte b[]) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - write(b); - return; - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - write(b); - bytesWritten = b.length; - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } - } - } - - @JIInstrumentationMethod - public void write(byte b[], int off, int len) throws IOException { - EventConfiguration eventConfiguration = EventConfigurations.FILE_WRITE; - if (!eventConfiguration.isEnabled()) { - write(b, off, len); - return; - } - long bytesWritten = 0; - long start = 0; - try { - start = EventConfiguration.timestamp(); - write(b, off, len); - bytesWritten = len; - } finally { - long duration = EventConfiguration.timestamp() - start; - if (eventConfiguration.shouldCommit(duration)) { - FileWriteEvent.commit(start, duration, path, bytesWritten); - } - } - } -} diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClassJFR.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClass.java similarity index 80% rename from test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClassJFR.java rename to test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClass.java index bf6216ae85a..f8c73173f60 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClassJFR.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClass.java @@ -24,16 +24,18 @@ /* * @test * @bug 8306929 - * @summary Verify should_clean_previous_versions when run with JFR and CDS + * @summary Verify should_clean_previous_versions when run with retransformation and CDS * @requires vm.jvmti * @requires vm.cds - * @requires vm.hasJFR * @requires vm.opt.final.ClassUnloading * @requires vm.flagless * @library /test/lib - * @run driver RedefineSharedClassJFR xshare-off - * @run driver RedefineSharedClassJFR xshare-on + * @run main RedefineClassHelper + * @run driver RedefineSharedClass xshare-off + * @run driver RedefineSharedClass xshare-on */ +import java.io.InputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -43,7 +45,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jtreg.SkippedException; -public class RedefineSharedClassJFR { +public class RedefineSharedClass { private static final String SHOULD_CLEAN_TRUE = "Class unloading: should_clean_previous_versions = true"; private static final String SHOULD_CLEAN_FALSE = "Class unloading: should_clean_previous_versions = false"; @@ -56,16 +58,16 @@ public class RedefineSharedClassJFR { throw new SkippedException("Supported platform"); } - // Test is run with JFR which will transform a number of classes. Depending - // on if the test is run with or without CDS the output will be different, - // due to the fact that shared classes can never be cleaned out after retranform. + // The test will redefine a single class below and depending on if the test + // is run with or without CDS the output will be different, due to the fact + // that shared classes can never be cleaned out after retranform. if (args.length > 0) { // When run with an argument the class is used as driver and should parse // the output to verify it is correct given the command line. List baseCommand = List.of( - "-XX:StartFlightRecording", + "-javaagent:redefineagent.jar", "-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace", - "RedefineSharedClassJFR"); + "RedefineSharedClass"); if (args[0].equals("xshare-off")) { // First case is with -Xshare:off. In this case no classes are shared @@ -104,8 +106,17 @@ public class RedefineSharedClassJFR { } } - // When run without any argument this class acts as test and we do a system GC - // to trigger cleaning and get the output we want to check. + // When run without arguments this class acts as the test. First redefining + // a class that we expect to be in the archive if used and the triggering a + // System.gc() to clean up. + RedefineClassHelper.redefineClass(java.io.RandomAccessFile.class, getClassBytes(java.io.RandomAccessFile.class)); System.gc(); } + + private static byte[] getClassBytes(Class clazz) throws IOException { + String name = "/" + clazz.getName().replace(".", "/") + ".class"; + try (InputStream is = clazz.getResourceAsStream(name)) { + return is.readAllBytes(); + } + } } diff --git a/test/jdk/jdk/jfr/jvm/TestGetEventWriterPackage.java b/test/jdk/jdk/jfr/jvm/TestGetEventWriterPackage.java index 95a112f5d78..065458d4ac7 100644 --- a/test/jdk/jdk/jfr/jvm/TestGetEventWriterPackage.java +++ b/test/jdk/jdk/jfr/jvm/TestGetEventWriterPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -46,13 +46,13 @@ public class TestGetEventWriterPackage { public static void main(String... args) throws Throwable { // --add-opens jdk.jfr/jdk.jfr.events=ALL-UNNAMED gives access to // the FileReadEvent class in the jdk.jfr module. - // When JFR is initialized the FileReadEvent is registered and an EventConfiguration object + // When JFR is initialized the DirectBufferStatisticsEvent is registered and an EventConfiguration object // assigned to its static field eventConfiguration try (Recording r = new Recording()) { r.start(); } // The tests gets the EventConfiguration object from the class - Classc = Class.forName("jdk.jfr.events.FileReadEvent"); + Classc = Class.forName("jdk.jfr.events.DirectBufferStatisticsEvent"); Field f = c.getDeclaredField("eventConfiguration"); f.setAccessible(true); Object o = f.get(null); diff --git a/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java b/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java index 8c8703dc9e6..186a87a12c2 100644 --- a/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java +++ b/test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -41,7 +41,7 @@ import jdk.test.lib.process.ProcessTools; */ public class TestRetransformUsingLog { - private static final String FILE_READ_FORCED_CLASS_LOAD = "Adding forced instrumentation for event type " + EventNames.FileRead + " during initial class load"; + private static final String FORCED_CLASS_LOAD = "Adding forced instrumentation for event type " + EventNames.DirectBufferStatistics + " during initial class load"; private static final String SIMPLE_EVENT_FORCED_CLASS_LOAD = "Adding forced instrumentation for event type jdk.test.lib.jfr.SimpleEvent during initial class load"; private static final String SIMPLE_EVENT_UNFORCED_CLASS_LOAD = "Adding instrumentation for event type jdk.test.lib.jfr.SimpleEvent during initial class load"; @@ -61,28 +61,28 @@ public class TestRetransformUsingLog { private static void testRecordingRetransFormFalse() throws Exception { startApp(true, false, out -> { - out.shouldContain(FILE_READ_FORCED_CLASS_LOAD); + out.shouldContain(FORCED_CLASS_LOAD); out.shouldContain(SIMPLE_EVENT_FORCED_CLASS_LOAD); }); } private static void testRecordingRetransFormTrue() throws Exception { startApp(true, true, out -> { - out.shouldContain(FILE_READ_FORCED_CLASS_LOAD); + out.shouldContain(FORCED_CLASS_LOAD); out.shouldContain(SIMPLE_EVENT_UNFORCED_CLASS_LOAD); }); } private static void testNoRecordingRetransFormFalse() throws Exception { startApp(false, false, out -> { - out.shouldNotContain(FILE_READ_FORCED_CLASS_LOAD); + out.shouldNotContain(FORCED_CLASS_LOAD); out.shouldContain(SIMPLE_EVENT_FORCED_CLASS_LOAD); }); } private static void testNoRecordingRetransFormTrue() throws Exception { startApp(false, true, out -> { - out.shouldNotContain(FILE_READ_FORCED_CLASS_LOAD); + out.shouldNotContain(FORCED_CLASS_LOAD); out.shouldNotContain(SIMPLE_EVENT_FORCED_CLASS_LOAD); out.shouldNotContain(SIMPLE_EVENT_UNFORCED_CLASS_LOAD); });