Skip to content

Commit b275bdd

Browse files
Tim PrinzingAlan Bateman
authored andcommitted
8308995: Update Network IO JFR events to be static mirror events
Reviewed-by: egahlin, alanb
1 parent e1870d3 commit b275bdd

File tree

13 files changed

+527
-387
lines changed

13 files changed

+527
-387
lines changed

make/test/BuildMicrobenchmark.gmk

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#
2-
# Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved.
2+
# Copyright (c) 2018, 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
@@ -105,6 +105,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \
105105
--add-exports java.base/jdk.internal.org.objectweb.asm=ALL-UNNAMED \
106106
--add-exports java.base/jdk.internal.org.objectweb.asm.tree=ALL-UNNAMED \
107107
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \
108+
--add-exports java.base/jdk.internal.event=ALL-UNNAMED \
108109
--enable-preview, \
109110
JAVA_FLAGS := --add-modules jdk.unsupported --limit-modules java.management \
110111
--add-exports java.base/jdk.internal.vm=ALL-UNNAMED \

src/java.base/share/classes/java/net/Socket.java

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525

2626
package java.net;
2727

28+
import jdk.internal.event.SocketReadEvent;
29+
import jdk.internal.event.SocketWriteEvent;
2830
import sun.security.util.SecurityConstants;
2931

3032
import java.io.InputStream;
@@ -1073,9 +1075,6 @@ public InputStream getInputStream() throws IOException {
10731075
/**
10741076
* An InputStream that delegates read/available operations to an underlying
10751077
* input stream. The close method is overridden to close the Socket.
1076-
*
1077-
* This class is instrumented by Java Flight Recorder (JFR) to get socket
1078-
* I/O events.
10791078
*/
10801079
private static class SocketInputStream extends InputStream {
10811080
private final Socket parent;
@@ -1092,6 +1091,16 @@ public int read() throws IOException {
10921091
}
10931092
@Override
10941093
public int read(byte[] b, int off, int len) throws IOException {
1094+
if (!SocketReadEvent.enabled()) {
1095+
return implRead(b, off, len);
1096+
}
1097+
long start = SocketReadEvent.timestamp();
1098+
int nbytes = implRead(b, off, len);
1099+
SocketReadEvent.offer(start, nbytes, parent.getRemoteSocketAddress(), getSoTimeout());
1100+
return nbytes;
1101+
}
1102+
1103+
private int implRead(byte[] b, int off, int len) throws IOException {
10951104
try {
10961105
return in.read(b, off, len);
10971106
} catch (SocketTimeoutException e) {
@@ -1105,6 +1114,16 @@ public int read(byte[] b, int off, int len) throws IOException {
11051114
throw e;
11061115
}
11071116
}
1117+
1118+
private int getSoTimeout() {
1119+
try {
1120+
return parent.getSoTimeout();
1121+
} catch (SocketException e) {
1122+
// ignored - avoiding exceptions in jfr event data gathering
1123+
}
1124+
return 0;
1125+
}
1126+
11081127
@Override
11091128
public int available() throws IOException {
11101129
return in.available();
@@ -1169,9 +1188,6 @@ public OutputStream getOutputStream() throws IOException {
11691188
/**
11701189
* An OutputStream that delegates write operations to an underlying output
11711190
* stream. The close method is overridden to close the Socket.
1172-
*
1173-
* This class is instrumented by Java Flight Recorder (JFR) to get socket
1174-
* I/O events.
11751191
*/
11761192
private static class SocketOutputStream extends OutputStream {
11771193
private final Socket parent;
@@ -1187,6 +1203,16 @@ public void write(int b) throws IOException {
11871203
}
11881204
@Override
11891205
public void write(byte[] b, int off, int len) throws IOException {
1206+
if (!SocketWriteEvent.enabled()) {
1207+
implWrite(b, off, len);
1208+
return;
1209+
}
1210+
long start = SocketWriteEvent.timestamp();
1211+
implWrite(b, off, len);
1212+
SocketWriteEvent.offer(start, len, parent.getRemoteSocketAddress());
1213+
}
1214+
1215+
private void implWrite(byte[] b, int off, int len) throws IOException {
11901216
try {
11911217
out.write(b, off, len);
11921218
} catch (InterruptedIOException e) {
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package jdk.internal.event;
27+
28+
29+
import java.net.InetSocketAddress;
30+
import java.net.SocketAddress;
31+
import java.net.UnixDomainSocketAddress;
32+
33+
/**
34+
* A JFR event for socket read operations. This event is mirrored in
35+
* {@code jdk.jfr.events.SocketReadEvent } where the metadata for the event is
36+
* provided with annotations. Some of the methods are replaced by generated
37+
* methods when jfr is enabled. Note that the order of the arguments of the
38+
* {@link #commit(long, long, String, String, int, long, long, boolean)} method
39+
* must be the same as the order of the fields.
40+
*/
41+
public class SocketReadEvent extends Event {
42+
43+
// THE ORDER OF THE FOLLOWING FIELDS IS IMPORTANT!
44+
// The order must match the argument order of the generated commit method.
45+
public String host;
46+
public String address;
47+
public int port;
48+
public long timeout;
49+
public long bytesRead;
50+
public boolean endOfStream;
51+
52+
/**
53+
* Actually commit a socket read event. The implementation
54+
* of this method is generated automatically if jfr is enabled.
55+
* The order of the fields must be the same as the parameters in this method.
56+
* {@code commit(..., String, String, int, long, long, boolean)}
57+
*
58+
* @param start timestamp of the start of the operation
59+
* @param duration time in nanoseconds to complete the operation
60+
* @param host remote host of the transfer
61+
* @param address remote address of the transfer
62+
* @param port remote port of the transfer
63+
* @param timeout timeout setting for the read
64+
* @param bytes number of bytes that were transferred
65+
* @param endOfStream has the end of the stream been reached
66+
*/
67+
public static void commit(long start, long duration, String host, String address, int port, long timeout, long bytes, boolean endOfStream) {
68+
// Generated by JFR
69+
}
70+
71+
/**
72+
* Determine if an event should be emitted. The duration of the operation
73+
* must exceed some threshold in order to commit the event. The implementation
74+
* of this method is generated automatically if jfr is enabled.
75+
*
76+
* @param duration time in nanoseconds to complete the operation
77+
* @return true if the event should be commited
78+
*/
79+
public static boolean shouldCommit(long duration) {
80+
// Generated by JFR
81+
return false;
82+
}
83+
84+
/**
85+
* Determine if this kind of event is enabled. The implementation
86+
* of this method is generated automatically if jfr is enabled.
87+
*
88+
* @return true if socket read events are enabled, false otherwise
89+
*/
90+
public static boolean enabled() {
91+
// Generated by JFR
92+
return false;
93+
}
94+
95+
/**
96+
* Fetch the current timestamp in nanoseconds. This method is used
97+
* to determine the start and end of an operation. The implementation
98+
* of this method is generated automatically if jfr is enabled.
99+
*
100+
* @return the current timestamp value
101+
*/
102+
public static long timestamp() {
103+
// Generated by JFR
104+
return 0L;
105+
}
106+
107+
/**
108+
* Helper method to offer the data needed to potentially commit an event.
109+
* The duration of the operation is computed using the current
110+
* timestamp and the given start time. If the duration is meets
111+
* or exceeds the configured value (determined by calling the generated method
112+
* {@link #shouldCommit(long)}), an event will be emitted by calling
113+
* {@link #commit(long, long, String, String, int, long, long, boolean)}.
114+
*
115+
* @param start the start time
116+
* @param nbytes how many bytes were transferred
117+
* @param remote the address of the remote socket
118+
* @param timeout maximum time to wait
119+
*/
120+
public static void offer(long start, long nbytes, SocketAddress remote, long timeout) {
121+
long duration = timestamp() - start;
122+
if (shouldCommit(duration)) {
123+
boolean eof = nbytes < 0 ? true : false;
124+
nbytes = nbytes < 0 ? 0 : nbytes;
125+
if (remote instanceof InetSocketAddress isa) {
126+
commit(start, duration, isa.getHostString(), isa.getAddress().getHostAddress(), isa.getPort(), timeout, nbytes, eof);
127+
} else if (remote instanceof UnixDomainSocketAddress udsa) {
128+
String path = "[" + udsa.getPath().toString() + "]";
129+
commit(start, duration, "Unix domain socket", path, 0, timeout, nbytes, eof);
130+
}
131+
}
132+
}
133+
134+
}
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation. Oracle designates this
8+
* particular file as subject to the "Classpath" exception as provided
9+
* by Oracle in the LICENSE file that accompanied this code.
10+
*
11+
* This code is distributed in the hope that it will be useful, but WITHOUT
12+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
* version 2 for more details (a copy is included in the LICENSE file that
15+
* accompanied this code).
16+
*
17+
* You should have received a copy of the GNU General Public License version
18+
* 2 along with this work; if not, write to the Free Software Foundation,
19+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
*
21+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
* or visit www.oracle.com if you need additional information or have any
23+
* questions.
24+
*/
25+
26+
package jdk.internal.event;
27+
28+
29+
import java.net.InetSocketAddress;
30+
import java.net.SocketAddress;
31+
import java.net.UnixDomainSocketAddress;
32+
33+
/**
34+
* A JFR event for socket write operations. This event is mirrored in
35+
* {@code jdk.jfr.events.SocketWriteEvent } where the metadata for the event is
36+
* provided with annotations. Some of the methods are replaced by generated
37+
* methods when jfr is enabled. Note that the order of the arguments of the
38+
* {@link #commit(long, long, String, String, int, long)} method
39+
* must be the same as the order of the fields.
40+
*/
41+
public class SocketWriteEvent extends Event {
42+
43+
// THE ORDER OF THE FOLLOWING FIELDS IS IMPORTANT!
44+
// The order must match the argument order of the generated commit method.
45+
public String host;
46+
public String address;
47+
public int port;
48+
public long bytesWritten;
49+
50+
/**
51+
* Actually commit a socket write event. This is generated automatically.
52+
* The order of the fields must be the same as the parameters in this method.
53+
* {@code commit(..., String, String, int, long)}
54+
*
55+
* @param start timestamp of the start of the operation
56+
* @param duration time in nanoseconds to complete the operation
57+
* @param host remote host of the transfer
58+
* @param address remote address of the transfer
59+
* @param port remote port of the transfer
60+
* @param bytes number of bytes that were transferred
61+
*/
62+
public static void commit(long start, long duration, String host, String address, int port, long bytes) {
63+
// Generated by JFR
64+
}
65+
66+
/**
67+
* Determine if an event should be emitted. The duration of the operation
68+
* must exceed some threshold in order to commit the event. The implementation
69+
* of this method is generated automatically if jfr is enabled.
70+
*
71+
* @param duration time in nanoseconds to complete the operation
72+
* @return true if the event should be commited
73+
*/
74+
public static boolean shouldCommit(long duration) {
75+
// Generated by JFR
76+
return false;
77+
}
78+
79+
/**
80+
* Determine if this kind of event is enabled. The implementation
81+
* of this method is generated automatically if jfr is enabled.
82+
*
83+
* @return true if socket write events are enabled, false otherwise
84+
*/
85+
public static boolean enabled() {
86+
// Generated by JFR
87+
return false;
88+
}
89+
90+
/**
91+
* Fetch the current timestamp in nanoseconds. This method is used
92+
* to determine the start and end of an operation. The implementation
93+
* of this method is generated automatically if jfr is enabled.
94+
*
95+
* @return the current timestamp value
96+
*/
97+
public static long timestamp() {
98+
// Generated by JFR
99+
return 0L;
100+
}
101+
102+
/**
103+
* Helper method to offer the data needed to potentially commit an event.
104+
* The duration of the operation is computed using the current
105+
* timestamp and the given start time. If the duration is meets
106+
* or exceeds the configured value (determined by calling the generated method
107+
* {@link #shouldCommit(long)}), an event will be emitted by calling
108+
* {@link #commit(long, long, String, String, int, long)}.
109+
*
110+
* @param start the start time
111+
* @param bytesWritten how many bytes were sent
112+
* @param remote the address of the remote socket being written to
113+
*/
114+
public static void offer(long start, long bytesWritten, SocketAddress remote) {
115+
long duration = timestamp() - start;
116+
if (shouldCommit(duration)) {
117+
long bytes = bytesWritten < 0 ? 0 : bytesWritten;
118+
if (remote instanceof InetSocketAddress isa) {
119+
commit(start, duration, isa.getHostString(), isa.getAddress().getHostAddress(), isa.getPort(), bytes);
120+
} else if (remote instanceof UnixDomainSocketAddress udsa) {
121+
String path = "[" + udsa.getPath().toString() + "]";
122+
commit(start, duration, "Unix domain socket", path, 0, bytes);
123+
}
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)