Skip to content

Commit 4a20691

Browse files
committedMay 30, 2024
8331876: JFR: Move file read and write events to java.base
Reviewed-by: mgronlun, alanb
1 parent f608918 commit 4a20691

20 files changed

+551
-662
lines changed
 

‎src/java.base/share/classes/java/io/FileInputStream.java

+57
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.nio.channels.FileChannel;
2929
import java.util.Arrays;
3030
import jdk.internal.util.ArraysSupport;
31+
import jdk.internal.event.FileReadEvent;
3132
import sun.nio.ch.FileChannelImpl;
3233

3334
/**
@@ -59,6 +60,12 @@ public class FileInputStream extends InputStream
5960
{
6061
private static final int DEFAULT_BUFFER_SIZE = 8192;
6162

63+
/**
64+
* Flag set by jdk.internal.event.JFRTracing to indicate if
65+
* file reads should be traced by JFR.
66+
*/
67+
private static boolean jfrTracing;
68+
6269
/* File Descriptor - handle to the open file */
6370
private final FileDescriptor fd;
6471

@@ -222,11 +229,36 @@ private void open(String name) throws FileNotFoundException {
222229
*/
223230
@Override
224231
public int read() throws IOException {
232+
if (jfrTracing && FileReadEvent.enabled()) {
233+
return traceRead0();
234+
}
225235
return read0();
226236
}
227237

228238
private native int read0() throws IOException;
229239

240+
private int traceRead0() throws IOException {
241+
int result = 0;
242+
boolean endOfFile = false;
243+
long bytesRead = 0;
244+
long start = 0;
245+
try {
246+
start = FileReadEvent.timestamp();
247+
result = read0();
248+
if (result < 0) {
249+
endOfFile = true;
250+
} else {
251+
bytesRead = 1;
252+
}
253+
} finally {
254+
long duration = FileReadEvent.timestamp() - start;
255+
if (FileReadEvent.shouldCommit(duration)) {
256+
FileReadEvent.commit(start, duration, path, bytesRead, endOfFile);
257+
}
258+
}
259+
return result;
260+
}
261+
230262
/**
231263
* Reads a subarray as a sequence of bytes.
232264
* @param b the data to be written
@@ -236,6 +268,25 @@ public int read() throws IOException {
236268
*/
237269
private native int readBytes(byte[] b, int off, int len) throws IOException;
238270

271+
private int traceReadBytes(byte b[], int off, int len) throws IOException {
272+
int bytesRead = 0;
273+
long start = 0;
274+
try {
275+
start = FileReadEvent.timestamp();
276+
bytesRead = readBytes(b, off, len);
277+
} finally {
278+
long duration = FileReadEvent.timestamp() - start;
279+
if (FileReadEvent.shouldCommit(duration)) {
280+
if (bytesRead < 0) {
281+
FileReadEvent.commit(start, duration, path, 0L, true);
282+
} else {
283+
FileReadEvent.commit(start, duration, path, bytesRead, false);
284+
}
285+
}
286+
}
287+
return bytesRead;
288+
}
289+
239290
/**
240291
* Reads up to {@code b.length} bytes of data from this input
241292
* stream into an array of bytes. This method blocks until some input
@@ -249,6 +300,9 @@ public int read() throws IOException {
249300
*/
250301
@Override
251302
public int read(byte[] b) throws IOException {
303+
if (jfrTracing && FileReadEvent.enabled()) {
304+
return traceReadBytes(b, 0, b.length);
305+
}
252306
return readBytes(b, 0, b.length);
253307
}
254308

@@ -268,6 +322,9 @@ public int read(byte[] b) throws IOException {
268322
*/
269323
@Override
270324
public int read(byte[] b, int off, int len) throws IOException {
325+
if (jfrTracing && FileReadEvent.enabled()) {
326+
return traceReadBytes(b, off, len);
327+
}
271328
return readBytes(b, off, len);
272329
}
273330

‎src/java.base/share/classes/java/io/FileOutputStream.java

+49
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.nio.channels.FileChannel;
2929
import jdk.internal.access.SharedSecrets;
3030
import jdk.internal.access.JavaIOFileDescriptorAccess;
31+
import jdk.internal.event.FileWriteEvent;
3132
import sun.nio.ch.FileChannelImpl;
3233

3334

@@ -68,6 +69,12 @@ public class FileOutputStream extends OutputStream
6869
private static final JavaIOFileDescriptorAccess FD_ACCESS =
6970
SharedSecrets.getJavaIOFileDescriptorAccess();
7071

72+
/**
73+
* Flag set by jdk.internal.event.JFRTracing to indicate if
74+
* file writes should be traced by JFR.
75+
*/
76+
private static boolean jfrTracing;
77+
7178
/**
7279
* The system dependent file descriptor.
7380
*/
@@ -297,6 +304,21 @@ private void open(String name, boolean append) throws FileNotFoundException {
297304
*/
298305
private native void write(int b, boolean append) throws IOException;
299306

307+
private void traceWrite(int b, boolean append) throws IOException {
308+
long bytesWritten = 0;
309+
long start = 0;
310+
try {
311+
start = FileWriteEvent.timestamp();
312+
write(b, append);
313+
bytesWritten = 1;
314+
} finally {
315+
long duration = FileWriteEvent.timestamp() - start;
316+
if (FileWriteEvent.shouldCommit(duration)) {
317+
FileWriteEvent.commit(start, duration, path, bytesWritten);
318+
}
319+
}
320+
}
321+
300322
/**
301323
* Writes the specified byte to this file output stream. Implements
302324
* the {@code write} method of {@code OutputStream}.
@@ -307,6 +329,10 @@ private void open(String name, boolean append) throws FileNotFoundException {
307329
@Override
308330
public void write(int b) throws IOException {
309331
boolean append = FD_ACCESS.getAppend(fd);
332+
if (jfrTracing && FileWriteEvent.enabled()) {
333+
traceWrite(b, append);
334+
return;
335+
}
310336
write(b, append);
311337
}
312338

@@ -322,6 +348,21 @@ public void write(int b) throws IOException {
322348
private native void writeBytes(byte[] b, int off, int len, boolean append)
323349
throws IOException;
324350

351+
private void traceWriteBytes(byte b[], int off, int len, boolean append) throws IOException {
352+
long bytesWritten = 0;
353+
long start = 0;
354+
try {
355+
start = FileWriteEvent.timestamp();
356+
writeBytes(b, off, len, append);
357+
bytesWritten = len;
358+
} finally {
359+
long duration = FileWriteEvent.timestamp() - start;
360+
if (FileWriteEvent.shouldCommit(duration)) {
361+
FileWriteEvent.commit(start, duration, path, bytesWritten);
362+
}
363+
}
364+
}
365+
325366
/**
326367
* Writes {@code b.length} bytes from the specified byte array
327368
* to this file output stream.
@@ -332,6 +373,10 @@ private native void writeBytes(byte[] b, int off, int len, boolean append)
332373
@Override
333374
public void write(byte[] b) throws IOException {
334375
boolean append = FD_ACCESS.getAppend(fd);
376+
if (jfrTracing && FileWriteEvent.enabled()) {
377+
traceWriteBytes(b, 0, b.length, append);
378+
return;
379+
}
335380
writeBytes(b, 0, b.length, append);
336381
}
337382

@@ -348,6 +393,10 @@ public void write(byte[] b) throws IOException {
348393
@Override
349394
public void write(byte[] b, int off, int len) throws IOException {
350395
boolean append = FD_ACCESS.getAppend(fd);
396+
if (jfrTracing && FileWriteEvent.enabled()) {
397+
traceWriteBytes(b, off, len, append);
398+
return;
399+
}
351400
writeBytes(b, off, len, append);
352401
}
353402

‎src/java.base/share/classes/java/io/RandomAccessFile.java

+101
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import jdk.internal.access.SharedSecrets;
3232
import jdk.internal.misc.Blocker;
3333
import jdk.internal.util.ByteArray;
34+
import jdk.internal.event.FileReadEvent;
35+
import jdk.internal.event.FileWriteEvent;
3436
import sun.nio.ch.FileChannelImpl;
3537

3638

@@ -68,6 +70,12 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable {
6870
private static final int O_DSYNC = 8;
6971
private static final int O_TEMPORARY = 16;
7072

73+
/**
74+
* Flag set by jdk.internal.event.JFRTracing to indicate if
75+
* file reads and writes should be traced by JFR.
76+
*/
77+
private static boolean jfrTracing;
78+
7179
private final FileDescriptor fd;
7280

7381
private final boolean rw;
@@ -376,11 +384,36 @@ private void open(String name, int mode) throws FileNotFoundException {
376384
* end-of-file has been reached.
377385
*/
378386
public int read() throws IOException {
387+
if (jfrTracing && FileReadEvent.enabled()) {
388+
return traceRead0();
389+
}
379390
return read0();
380391
}
381392

382393
private native int read0() throws IOException;
383394

395+
private int traceRead0() throws IOException {
396+
int result = 0;
397+
long bytesRead = 0;
398+
boolean endOfFile = false;
399+
long start = 0;
400+
try {
401+
start = FileReadEvent.timestamp();
402+
result = read0();
403+
if (result < 0) {
404+
endOfFile = true;
405+
} else {
406+
bytesRead = 1;
407+
}
408+
} finally {
409+
long duration = FileReadEvent.timestamp() - start;
410+
if (FileReadEvent.shouldCommit(duration)) {
411+
FileReadEvent.commit(start, duration, path, bytesRead, endOfFile);
412+
}
413+
}
414+
return result;
415+
}
416+
384417
/**
385418
* Reads a sub array as a sequence of bytes.
386419
* @param b the buffer into which the data is read.
@@ -389,11 +422,33 @@ public int read() throws IOException {
389422
* @throws IOException If an I/O error has occurred.
390423
*/
391424
private int readBytes(byte[] b, int off, int len) throws IOException {
425+
if (jfrTracing && FileReadEvent.enabled()) {
426+
return traceReadBytes0(b, off, len);
427+
}
392428
return readBytes0(b, off, len);
393429
}
394430

395431
private native int readBytes0(byte[] b, int off, int len) throws IOException;
396432

433+
private int traceReadBytes0(byte b[], int off, int len) throws IOException {
434+
int bytesRead = 0;
435+
long start = 0;
436+
try {
437+
start = FileReadEvent.timestamp();
438+
bytesRead = readBytes0(b, off, len);
439+
} finally {
440+
long duration = FileReadEvent.timestamp() - start;
441+
if (FileReadEvent.shouldCommit(duration)) {
442+
if (bytesRead < 0) {
443+
FileReadEvent.commit(start, duration, path, 0L, true);
444+
} else {
445+
FileReadEvent.commit(start, duration, path, bytesRead, false);
446+
}
447+
}
448+
}
449+
return bytesRead;
450+
}
451+
397452
/**
398453
* Reads up to {@code len} bytes of data from this file into an
399454
* array of bytes. This method blocks until at least one byte of input
@@ -537,6 +592,14 @@ public int skipBytes(int n) throws IOException {
537592
* @throws IOException if an I/O error occurs.
538593
*/
539594
public void write(int b) throws IOException {
595+
if (jfrTracing && FileWriteEvent.enabled()) {
596+
traceImplWrite(b);
597+
return;
598+
}
599+
implWrite(b);
600+
}
601+
602+
private void implWrite(int b) throws IOException {
540603
boolean attempted = Blocker.begin(sync);
541604
try {
542605
write0(b);
@@ -545,6 +608,21 @@ public void write(int b) throws IOException {
545608
}
546609
}
547610

611+
private void traceImplWrite(int b) throws IOException {
612+
long bytesWritten = 0;
613+
long start = 0;
614+
try {
615+
start = FileWriteEvent.timestamp();
616+
implWrite(b);
617+
bytesWritten = 1;
618+
} finally {
619+
long duration = FileWriteEvent.timestamp() - start;
620+
if (FileWriteEvent.shouldCommit(duration)) {
621+
FileWriteEvent.commit(start, duration, path, bytesWritten);
622+
}
623+
}
624+
}
625+
548626
private native void write0(int b) throws IOException;
549627

550628
/**
@@ -556,6 +634,14 @@ public void write(int b) throws IOException {
556634
* @throws IOException If an I/O error has occurred.
557635
*/
558636
private void writeBytes(byte[] b, int off, int len) throws IOException {
637+
if (jfrTracing && FileWriteEvent.enabled()) {
638+
traceImplWriteBytes(b, off, len);
639+
return;
640+
}
641+
implWriteBytes(b, off, len);
642+
}
643+
644+
private void implWriteBytes(byte[] b, int off, int len) throws IOException {
559645
boolean attempted = Blocker.begin(sync);
560646
try {
561647
writeBytes0(b, off, len);
@@ -564,6 +650,21 @@ private void writeBytes(byte[] b, int off, int len) throws IOException {
564650
}
565651
}
566652

653+
private void traceImplWriteBytes(byte b[], int off, int len) throws IOException {
654+
long bytesWritten = 0;
655+
long start = 0;
656+
try {
657+
start = FileWriteEvent.timestamp();
658+
implWriteBytes(b, off, len);
659+
bytesWritten = len;
660+
} finally {
661+
long duration = FileWriteEvent.timestamp() - start;
662+
if (FileWriteEvent.shouldCommit(duration)) {
663+
FileWriteEvent.commit(start, duration, path, bytesWritten);
664+
}
665+
}
666+
}
667+
567668
private native void writeBytes0(byte[] b, int off, int len) throws IOException;
568669

569670
/**

‎src/java.base/share/classes/java/lang/Throwable.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ public class Throwable implements Serializable {
120120
private static final long serialVersionUID = -3042686055658047285L;
121121

122122
/**
123-
* Flag that determines if exceptions should be traced by JFR
123+
* Flag set by jdk.internal.event.JFRTracing to indicate if
124+
* exceptions should be traced by JFR.
124125
*/
125126
static volatile boolean jfrTracing;
126127

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.internal.event;
26+
27+
/**
28+
* Event recording file reads.
29+
*/
30+
public final class FileReadEvent extends Event {
31+
32+
// The order of these fields must be the same as the parameters in
33+
// commit(..., String, long, boolean)
34+
public String path;
35+
public long bytesRead;
36+
public boolean endOfFile;
37+
38+
public static boolean enabled() {
39+
// Generated by JFR
40+
return false;
41+
}
42+
43+
public static long timestamp() {
44+
// Generated by JFR
45+
return 0L;
46+
}
47+
48+
public static boolean shouldCommit(long duration) {
49+
// Generated by JFR
50+
return false;
51+
}
52+
53+
public static void commit(long start, long duration, String path, long bytesRead, boolean endOfFile) {
54+
// Generated by JFR
55+
}
56+
}

‎src/jdk.jfr/share/classes/jdk/jfr/events/EventConfigurations.java ‎src/java.base/share/classes/jdk/internal/event/FileWriteEvent.java

+29-7
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -22,12 +22,34 @@
2222
* or visit www.oracle.com if you need additional information or have any
2323
* questions.
2424
*/
25+
package jdk.internal.event;
2526

26-
package jdk.jfr.events;
27-
import jdk.jfr.internal.JVMSupport;
28-
import jdk.jfr.internal.event.EventConfiguration;
27+
/**
28+
* Event recording file writes.
29+
*/
30+
public final class FileWriteEvent extends Event {
31+
32+
// The order of these fields must be the same as the parameters in
33+
// commit(..., String, long)
34+
public String path;
35+
public long bytesWritten;
36+
37+
public static boolean enabled() {
38+
// Generated by JFR
39+
return false;
40+
}
41+
42+
public static long timestamp() {
43+
// Generated by JFR
44+
return 0L;
45+
}
46+
47+
public static boolean shouldCommit(long duration) {
48+
// Generated by JFR
49+
return false;
50+
}
2951

30-
public final class EventConfigurations {
31-
public static final EventConfiguration FILE_READ = JVMSupport.getConfiguration(FileReadEvent.class);
32-
public static final EventConfiguration FILE_WRITE = JVMSupport.getConfiguration(FileWriteEvent.class);
52+
public static void commit(long start, long duration, String path, long bytesWritten) {
53+
// Generated by JFR
54+
}
3355
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
package jdk.internal.event;
26+
27+
import sun.nio.ch.FileChannelImpl;
28+
import java.io.FileInputStream;
29+
import java.io.FileOutputStream;
30+
import java.io.RandomAccessFile;
31+
import java.lang.Throwable;
32+
import java.lang.reflect.Field;
33+
34+
/**
35+
* Helper class to enable JFR tracing.
36+
*/
37+
public final class JFRTracing {
38+
39+
public static void enable() throws NoSuchFieldException, IllegalAccessException {
40+
enable(Throwable.class);
41+
enable(FileInputStream.class);
42+
enable(FileOutputStream.class);
43+
enable(FileChannelImpl.class);
44+
enable(RandomAccessFile.class);
45+
}
46+
47+
private static void enable(Class<?> clazz) throws NoSuchFieldException, IllegalAccessException {
48+
Field field = clazz.getDeclaredField("jfrTracing");
49+
field.setAccessible(true);
50+
field.setBoolean(null, true);
51+
}
52+
}

‎src/java.base/share/classes/jdk/internal/event/ThrowableTracer.java

+1-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,6 @@
2424
*/
2525
package jdk.internal.event;
2626

27-
import java.lang.reflect.Field;
2827
import java.util.concurrent.atomic.AtomicLong;
2928

3029
/**
@@ -34,12 +33,6 @@ public final class ThrowableTracer {
3433

3534
private static final AtomicLong numThrowables = new AtomicLong();
3635

37-
public static void enable() throws NoSuchFieldException, IllegalAccessException {
38-
Field field = Throwable.class.getDeclaredField("jfrTracing");
39-
field.setAccessible(true);
40-
field.setBoolean(null, true);
41-
}
42-
4336
public static void traceError(Class<?> clazz, String message) {
4437
if (OutOfMemoryError.class.isAssignableFrom(clazz)) {
4538
return;

‎src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java

+154-5
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
import jdk.internal.misc.VM.BufferPool;
6161
import jdk.internal.ref.Cleaner;
6262
import jdk.internal.ref.CleanerFactory;
63-
63+
import jdk.internal.event.FileReadEvent;
64+
import jdk.internal.event.FileWriteEvent;
6465
import jdk.internal.access.foreign.UnmapperProxy;
6566

6667
public class FileChannelImpl
@@ -73,6 +74,10 @@ public class FileChannelImpl
7374
// Used to make native read and write calls
7475
private static final FileDispatcher nd = new FileDispatcherImpl();
7576

77+
// Flag set by jdk.internal.event.JFRTracing to indicate if
78+
// file reads and writes should be traced by JFR.
79+
private static boolean jfrTracing;
80+
7681
// File descriptor
7782
private final FileDescriptor fd;
7883

@@ -220,6 +225,13 @@ protected void implCloseChannel() throws IOException {
220225

221226
@Override
222227
public int read(ByteBuffer dst) throws IOException {
228+
if (jfrTracing && FileReadEvent.enabled()) {
229+
return traceImplRead(dst);
230+
}
231+
return implRead(dst);
232+
}
233+
234+
private int implRead(ByteBuffer dst) throws IOException {
223235
ensureOpen();
224236
if (!readable)
225237
throw new NonReadableChannelException();
@@ -250,8 +262,34 @@ public int read(ByteBuffer dst) throws IOException {
250262
}
251263
}
252264

265+
private int traceImplRead(ByteBuffer dst) throws IOException {
266+
int bytesRead = 0;
267+
long start = 0;
268+
try {
269+
start = FileReadEvent.timestamp();
270+
bytesRead = implRead(dst);
271+
} finally {
272+
long duration = FileReadEvent.timestamp() - start;
273+
if (FileReadEvent.shouldCommit(duration)) {
274+
if (bytesRead < 0) {
275+
FileReadEvent.commit(start, duration, path, 0L, true);
276+
} else {
277+
FileReadEvent.commit(start, duration, path, bytesRead, false);
278+
}
279+
}
280+
}
281+
return bytesRead;
282+
}
283+
253284
@Override
254-
public long read(ByteBuffer[] dsts, int offset, int length)
285+
public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
286+
if (jfrTracing && FileReadEvent.enabled()) {
287+
return traceImplRead(dsts, offset, length);
288+
}
289+
return implRead(dsts, offset, length);
290+
}
291+
292+
private long implRead(ByteBuffer[] dsts, int offset, int length)
255293
throws IOException
256294
{
257295
Objects.checkFromIndexSize(offset, length, dsts.length);
@@ -286,8 +324,34 @@ public long read(ByteBuffer[] dsts, int offset, int length)
286324
}
287325
}
288326

327+
private long traceImplRead(ByteBuffer[] dsts, int offset, int length) throws IOException {
328+
long bytesRead = 0;
329+
long start = 0;
330+
try {
331+
start = FileReadEvent.timestamp();
332+
bytesRead = implRead(dsts, offset, length);
333+
} finally {
334+
long duration = FileReadEvent.timestamp() - start;
335+
if (FileReadEvent.shouldCommit(duration)) {
336+
if (bytesRead < 0) {
337+
FileReadEvent.commit(start, duration, path, 0L, true);
338+
} else {
339+
FileReadEvent.commit(start, duration, path, bytesRead, false);
340+
}
341+
}
342+
}
343+
return bytesRead;
344+
}
345+
289346
@Override
290347
public int write(ByteBuffer src) throws IOException {
348+
if (jfrTracing && FileWriteEvent.enabled()) {
349+
return traceImplWrite(src);
350+
}
351+
return implWrite(src);
352+
}
353+
354+
private int implWrite(ByteBuffer src) throws IOException {
291355
ensureOpen();
292356
if (!writable)
293357
throw new NonWritableChannelException();
@@ -319,10 +383,31 @@ public int write(ByteBuffer src) throws IOException {
319383
}
320384
}
321385

386+
private int traceImplWrite(ByteBuffer src) throws IOException {
387+
int bytesWritten = 0;
388+
long start = 0;
389+
try {
390+
start = FileWriteEvent.timestamp();
391+
bytesWritten = implWrite(src);
392+
} finally {
393+
long duration = FileWriteEvent.timestamp() - start;
394+
if (FileWriteEvent.shouldCommit(duration)) {
395+
long bytes = bytesWritten > 0 ? bytesWritten : 0;
396+
FileWriteEvent.commit(start, duration, path, bytes);
397+
}
398+
}
399+
return bytesWritten;
400+
}
401+
322402
@Override
323-
public long write(ByteBuffer[] srcs, int offset, int length)
324-
throws IOException
325-
{
403+
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
404+
if (jfrTracing && FileWriteEvent.enabled()) {
405+
return traceImplWrite(srcs, offset, length);
406+
}
407+
return implWrite(srcs, offset, length);
408+
}
409+
410+
private long implWrite(ByteBuffer[] srcs, int offset, int length) throws IOException {
326411
Objects.checkFromIndexSize(offset, length, srcs.length);
327412
ensureOpen();
328413
if (!writable)
@@ -354,6 +439,21 @@ public long write(ByteBuffer[] srcs, int offset, int length)
354439
}
355440
}
356441

442+
private long traceImplWrite(ByteBuffer[] srcs, int offset, int length) throws IOException {
443+
long bytesWritten = 0;
444+
long start = 0;
445+
try {
446+
start = FileWriteEvent.timestamp();
447+
bytesWritten = implWrite(srcs, offset, length);
448+
} finally {
449+
long duration = FileWriteEvent.timestamp() - start;
450+
if (FileWriteEvent.shouldCommit(duration)) {
451+
long bytes = bytesWritten > 0 ? bytesWritten : 0;
452+
FileWriteEvent.commit(start, duration, path, bytes);
453+
}
454+
}
455+
return bytesWritten;
456+
}
357457
// -- Other operations --
358458

359459
@Override
@@ -1028,6 +1128,13 @@ public long transferFrom(ReadableByteChannel src, long position, long count)
10281128

10291129
@Override
10301130
public int read(ByteBuffer dst, long position) throws IOException {
1131+
if (jfrTracing && FileReadEvent.enabled()) {
1132+
return traceImplRead(dst, position);
1133+
}
1134+
return implRead(dst, position);
1135+
}
1136+
1137+
private int implRead(ByteBuffer dst, long position) throws IOException {
10311138
if (dst == null)
10321139
throw new NullPointerException();
10331140
if (position < 0)
@@ -1046,6 +1153,25 @@ public int read(ByteBuffer dst, long position) throws IOException {
10461153
}
10471154
}
10481155

1156+
private int traceImplRead(ByteBuffer dst, long position) throws IOException {
1157+
int bytesRead = 0;
1158+
long start = 0;
1159+
try {
1160+
start = FileReadEvent.timestamp();
1161+
bytesRead = implRead(dst, position);
1162+
} finally {
1163+
long duration = FileReadEvent.timestamp() - start;
1164+
if (FileReadEvent.shouldCommit(duration)) {
1165+
if (bytesRead < 0) {
1166+
FileReadEvent.commit(start, duration, path, 0L, true);
1167+
} else {
1168+
FileReadEvent.commit(start, duration, path, bytesRead, false);
1169+
}
1170+
}
1171+
}
1172+
return bytesRead;
1173+
}
1174+
10491175
private int readInternal(ByteBuffer dst, long position) throws IOException {
10501176
assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
10511177
int n = 0;
@@ -1074,6 +1200,13 @@ private int readInternal(ByteBuffer dst, long position) throws IOException {
10741200

10751201
@Override
10761202
public int write(ByteBuffer src, long position) throws IOException {
1203+
if (jfrTracing && FileReadEvent.enabled()) {
1204+
return traceImplWrite(src, position);
1205+
}
1206+
return implWrite(src, position);
1207+
}
1208+
1209+
private int implWrite(ByteBuffer src, long position) throws IOException {
10771210
if (src == null)
10781211
throw new NullPointerException();
10791212
if (position < 0)
@@ -1092,6 +1225,22 @@ public int write(ByteBuffer src, long position) throws IOException {
10921225
}
10931226
}
10941227

1228+
private int traceImplWrite(ByteBuffer src, long position) throws IOException {
1229+
int bytesWritten = 0;
1230+
long start = 0;
1231+
try {
1232+
start = FileWriteEvent.timestamp();
1233+
bytesWritten = implWrite(src, position);
1234+
} finally {
1235+
long duration = FileWriteEvent.timestamp() - start;
1236+
if (FileWriteEvent.shouldCommit(duration)) {
1237+
long bytes = bytesWritten > 0 ? bytesWritten : 0;
1238+
FileWriteEvent.commit(start, duration, path, bytes);
1239+
}
1240+
}
1241+
return bytesWritten;
1242+
}
1243+
10951244
private int writeInternal(ByteBuffer src, long position) throws IOException {
10961245
assert !nd.needsPositionLock() || Thread.holdsLock(positionLock);
10971246
int n = 0;

‎src/jdk.jfr/share/classes/jdk/jfr/events/FileReadEvent.java

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,15 +31,14 @@
3131
import jdk.jfr.DataAmount;
3232
import jdk.jfr.Name;
3333
import jdk.jfr.internal.Type;
34+
import jdk.jfr.internal.MirrorEvent;
3435

3536
@Name(Type.EVENT_NAME_PREFIX + "FileRead")
3637
@Label("File Read")
3738
@Category("Java Application")
3839
@Description("Reading data from a file")
39-
public final class FileReadEvent extends AbstractJDKEvent {
40-
41-
// The order of these fields must be the same as the parameters in
42-
// commit(..., String, long, boolean)
40+
@StackFilter({"java.io.FileInputStream", "java.io.RandomAccessFile", "sun.nio.ch.FileChannelImpl"})
41+
public final class FileReadEvent extends MirrorEvent {
4342

4443
@Label("Path")
4544
@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 {
5453
@Description("If end of file was reached")
5554
public boolean endOfFile;
5655

57-
public static void commit(long start, long duration, String path, long bytesRead, boolean endOfFile) {
58-
// Generated
59-
}
6056
}

‎src/jdk.jfr/share/classes/jdk/jfr/events/FileWriteEvent.java

+4-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -31,15 +31,14 @@
3131
import jdk.jfr.DataAmount;
3232
import jdk.jfr.Name;
3333
import jdk.jfr.internal.Type;
34+
import jdk.jfr.internal.MirrorEvent;
3435

3536
@Name(Type.EVENT_NAME_PREFIX + "FileWrite")
3637
@Label("File Write")
3738
@Category("Java Application")
3839
@Description("Writing data to a file")
39-
public final class FileWriteEvent extends AbstractJDKEvent {
40-
41-
// The order of these fields must be the same as the parameters in
42-
// commit(..., String, long)
40+
@StackFilter({"java.io.FileOutputStream", "java.io.RandomAccessFile", "sun.nio.ch.FileChannelImpl"})
41+
public final class FileWriteEvent extends MirrorEvent {
4342

4443
@Label("Path")
4544
@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 {
4948
@Description("Number of bytes written to the file")
5049
@DataAmount
5150
public long bytesWritten;
52-
53-
public static void commit(long start, long duration, String path, long bytesWritten) {
54-
// Generated
55-
}
5651
}

‎src/jdk.jfr/share/classes/jdk/jfr/internal/MirrorEvents.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -32,6 +32,8 @@
3232
import jdk.jfr.events.ExceptionStatisticsEvent;
3333
import jdk.jfr.events.ExceptionThrownEvent;
3434
import jdk.jfr.events.FileForceEvent;
35+
import jdk.jfr.events.FileReadEvent;
36+
import jdk.jfr.events.FileWriteEvent;
3537
import jdk.jfr.events.ProcessStartEvent;
3638
import jdk.jfr.events.SecurityPropertyModificationEvent;
3739
import jdk.jfr.events.SecurityProviderServiceEvent;
@@ -57,6 +59,8 @@ final class MirrorEvents {
5759
static {
5860
register("jdk.internal.event.DeserializationEvent", DeserializationEvent.class);
5961
register("jdk.internal.event.FileForceEvent", FileForceEvent.class);
62+
register("jdk.internal.event.FileReadEvent", FileReadEvent.class);
63+
register("jdk.internal.event.FileWriteEvent", FileWriteEvent.class);
6064
register("jdk.internal.event.ProcessStartEvent", ProcessStartEvent.class);
6165
register("jdk.internal.event.SecurityPropertyModificationEvent", SecurityPropertyModificationEvent.class);
6266
register("jdk.internal.event.SecurityProviderServiceEvent", SecurityProviderServiceEvent.class);

‎src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileChannelImplInstrumentor.java

-183
This file was deleted.

‎src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileInputStreamInstrumentor.java

-119
This file was deleted.

‎src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/FileOutputStreamInstrumentor.java

-107
This file was deleted.

‎src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/JDKEvents.java

+5-10
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -30,6 +30,7 @@
3030
import java.util.Properties;
3131

3232
import jdk.internal.access.SharedSecrets;
33+
import jdk.internal.event.JFRTracing;
3334
import jdk.internal.event.ThrowableTracer;
3435
import jdk.jfr.Event;
3536
import jdk.jfr.events.ActiveRecordingEvent;
@@ -41,8 +42,6 @@
4142
import jdk.jfr.events.ContainerMemoryUsageEvent;
4243
import jdk.jfr.events.DirectBufferStatisticsEvent;
4344
import jdk.jfr.events.FileForceEvent;
44-
import jdk.jfr.events.FileReadEvent;
45-
import jdk.jfr.events.FileWriteEvent;
4645
import jdk.jfr.events.InitialSecurityPropertyEvent;
4746

4847
import jdk.jfr.internal.JVM;
@@ -57,8 +56,6 @@
5756
public final class JDKEvents {
5857

5958
private static final Class<?>[] eventClasses = {
60-
FileReadEvent.class,
61-
FileWriteEvent.class,
6259
ActiveSettingEvent.class,
6360
ActiveRecordingEvent.class,
6461
// jdk.internal.event.* classes need their mirror
@@ -68,6 +65,8 @@ public final class JDKEvents {
6865
jdk.internal.event.ExceptionStatisticsEvent.class,
6966
jdk.internal.event.ExceptionThrownEvent.class,
7067
jdk.internal.event.FileForceEvent.class,
68+
jdk.internal.event.FileReadEvent.class,
69+
jdk.internal.event.FileWriteEvent.class,
7170
jdk.internal.event.ProcessStartEvent.class,
7271
jdk.internal.event.SecurityPropertyModificationEvent.class,
7372
jdk.internal.event.SecurityProviderServiceEvent.class,
@@ -88,10 +87,6 @@ public final class JDKEvents {
8887

8988
// This is a list of the classes with instrumentation code that should be applied.
9089
private static final Class<?>[] instrumentationClasses = new Class<?>[] {
91-
FileInputStreamInstrumentor.class,
92-
FileOutputStreamInstrumentor.class,
93-
RandomAccessFileInstrumentor.class,
94-
FileChannelImplInstrumentor.class
9590
};
9691

9792
private static final Class<?>[] targetClasses = new Class<?>[instrumentationClasses.length];
@@ -118,7 +113,7 @@ public static synchronized void initialize() {
118113
PeriodicEvents.addJDKEvent(InitialSecurityPropertyEvent.class, emitInitialSecurityProperties);
119114

120115
initializeContainerEvents();
121-
ThrowableTracer.enable();
116+
JFRTracing.enable();
122117
initializationTriggered = true;
123118
}
124119
} catch (Exception e) {

‎src/jdk.jfr/share/classes/jdk/jfr/internal/instrument/RandomAccessFileInstrumentor.java

-183
This file was deleted.

‎test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClassJFR.java ‎test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineSharedClass.java

+23-12
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,18 @@
2424
/*
2525
* @test
2626
* @bug 8306929
27-
* @summary Verify should_clean_previous_versions when run with JFR and CDS
27+
* @summary Verify should_clean_previous_versions when run with retransformation and CDS
2828
* @requires vm.jvmti
2929
* @requires vm.cds
30-
* @requires vm.hasJFR
3130
* @requires vm.opt.final.ClassUnloading
3231
* @requires vm.flagless
3332
* @library /test/lib
34-
* @run driver RedefineSharedClassJFR xshare-off
35-
* @run driver RedefineSharedClassJFR xshare-on
33+
* @run main RedefineClassHelper
34+
* @run driver RedefineSharedClass xshare-off
35+
* @run driver RedefineSharedClass xshare-on
3636
*/
37+
import java.io.InputStream;
38+
import java.io.IOException;
3739
import java.util.ArrayList;
3840
import java.util.List;
3941

@@ -43,7 +45,7 @@
4345

4446
import jtreg.SkippedException;
4547

46-
public class RedefineSharedClassJFR {
48+
public class RedefineSharedClass {
4749

4850
private static final String SHOULD_CLEAN_TRUE = "Class unloading: should_clean_previous_versions = true";
4951
private static final String SHOULD_CLEAN_FALSE = "Class unloading: should_clean_previous_versions = false";
@@ -56,16 +58,16 @@ public static void main(String[] args) throws Exception {
5658
throw new SkippedException("Supported platform");
5759
}
5860

59-
// Test is run with JFR which will transform a number of classes. Depending
60-
// on if the test is run with or without CDS the output will be different,
61-
// due to the fact that shared classes can never be cleaned out after retranform.
61+
// The test will redefine a single class below and depending on if the test
62+
// is run with or without CDS the output will be different, due to the fact
63+
// that shared classes can never be cleaned out after retranform.
6264
if (args.length > 0) {
6365
// When run with an argument the class is used as driver and should parse
6466
// the output to verify it is correct given the command line.
6567
List<String> baseCommand = List.of(
66-
"-XX:StartFlightRecording",
68+
"-javaagent:redefineagent.jar",
6769
"-Xlog:redefine+class+iklass+add=trace,redefine+class+iklass+purge=trace",
68-
"RedefineSharedClassJFR");
70+
"RedefineSharedClass");
6971

7072
if (args[0].equals("xshare-off")) {
7173
// First case is with -Xshare:off. In this case no classes are shared
@@ -104,8 +106,17 @@ public static void main(String[] args) throws Exception {
104106
}
105107
}
106108

107-
// When run without any argument this class acts as test and we do a system GC
108-
// to trigger cleaning and get the output we want to check.
109+
// When run without arguments this class acts as the test. First redefining
110+
// a class that we expect to be in the archive if used and the triggering a
111+
// System.gc() to clean up.
112+
RedefineClassHelper.redefineClass(java.io.RandomAccessFile.class, getClassBytes(java.io.RandomAccessFile.class));
109113
System.gc();
110114
}
115+
116+
private static byte[] getClassBytes(Class clazz) throws IOException {
117+
String name = "/" + clazz.getName().replace(".", "/") + ".class";
118+
try (InputStream is = clazz.getResourceAsStream(name)) {
119+
return is.readAllBytes();
120+
}
121+
}
111122
}

‎test/jdk/jdk/jfr/jvm/TestGetEventWriterPackage.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -46,13 +46,13 @@ static class PackageUnlockEvent extends Event {
4646
public static void main(String... args) throws Throwable {
4747
// --add-opens jdk.jfr/jdk.jfr.events=ALL-UNNAMED gives access to
4848
// the FileReadEvent class in the jdk.jfr module.
49-
// When JFR is initialized the FileReadEvent is registered and an EventConfiguration object
49+
// When JFR is initialized the DirectBufferStatisticsEvent is registered and an EventConfiguration object
5050
// assigned to its static field eventConfiguration
5151
try (Recording r = new Recording()) {
5252
r.start();
5353
}
5454
// The tests gets the EventConfiguration object from the class
55-
Class<?>c = Class.forName("jdk.jfr.events.FileReadEvent");
55+
Class<?>c = Class.forName("jdk.jfr.events.DirectBufferStatisticsEvent");
5656
Field f = c.getDeclaredField("eventConfiguration");
5757
f.setAccessible(true);
5858
Object o = f.get(null);

‎test/jdk/jdk/jfr/startupargs/TestRetransformUsingLog.java

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@
4141
*/
4242
public class TestRetransformUsingLog {
4343

44-
private static final String FILE_READ_FORCED_CLASS_LOAD = "Adding forced instrumentation for event type " + EventNames.FileRead + " during initial class load";
44+
private static final String FORCED_CLASS_LOAD = "Adding forced instrumentation for event type " + EventNames.DirectBufferStatistics + " during initial class load";
4545
private static final String SIMPLE_EVENT_FORCED_CLASS_LOAD = "Adding forced instrumentation for event type jdk.test.lib.jfr.SimpleEvent during initial class load";
4646
private static final String SIMPLE_EVENT_UNFORCED_CLASS_LOAD = "Adding instrumentation for event type jdk.test.lib.jfr.SimpleEvent during initial class load";
4747

@@ -61,28 +61,28 @@ public static void main(String[] args) throws Exception {
6161

6262
private static void testRecordingRetransFormFalse() throws Exception {
6363
startApp(true, false, out -> {
64-
out.shouldContain(FILE_READ_FORCED_CLASS_LOAD);
64+
out.shouldContain(FORCED_CLASS_LOAD);
6565
out.shouldContain(SIMPLE_EVENT_FORCED_CLASS_LOAD);
6666
});
6767
}
6868

6969
private static void testRecordingRetransFormTrue() throws Exception {
7070
startApp(true, true, out -> {
71-
out.shouldContain(FILE_READ_FORCED_CLASS_LOAD);
71+
out.shouldContain(FORCED_CLASS_LOAD);
7272
out.shouldContain(SIMPLE_EVENT_UNFORCED_CLASS_LOAD);
7373
});
7474
}
7575

7676
private static void testNoRecordingRetransFormFalse() throws Exception {
7777
startApp(false, false, out -> {
78-
out.shouldNotContain(FILE_READ_FORCED_CLASS_LOAD);
78+
out.shouldNotContain(FORCED_CLASS_LOAD);
7979
out.shouldContain(SIMPLE_EVENT_FORCED_CLASS_LOAD);
8080
});
8181
}
8282

8383
private static void testNoRecordingRetransFormTrue() throws Exception {
8484
startApp(false, true, out -> {
85-
out.shouldNotContain(FILE_READ_FORCED_CLASS_LOAD);
85+
out.shouldNotContain(FORCED_CLASS_LOAD);
8686
out.shouldNotContain(SIMPLE_EVENT_FORCED_CLASS_LOAD);
8787
out.shouldNotContain(SIMPLE_EVENT_UNFORCED_CLASS_LOAD);
8888
});

0 commit comments

Comments
 (0)
Please sign in to comment.