undefect. CWE-407 — 63 sites patched across 27 ecosystems

Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com

Patches, unit tests, benchmarks, whitepaper, and outreach briefs.
Public domain — no copyright claimed. Use freely.
This commit is contained in:
russell@unturf.com 2026-03-26 17:11:57 -04:00
commit 0a580b313d
70422 changed files with 17213626 additions and 0 deletions

View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 2020, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.io.IOException;
import java.net.InetAddress;
import java.util.concurrent.TimeUnit;
/**
* Benchmark DatagramChannel send/receive.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
public class DatagramChannelSendReceive {
private int counter = 0;
private ByteBuffer buf;
private DatagramChannel channel1, channel2, connectedWriteChannel,
connectedReadChannel, multipleReceiveChannel, multipleSendChannel;
private DatagramChannel[] dca;
@Param({"128", "32768"})
public int size;
@Param({"4"})
public int channelCount;
@Param({"true"})
public boolean useDirectBuffer;
@Setup
public void setUp() throws IOException {
buf = (useDirectBuffer) ? ByteBuffer.allocateDirect(size) :
ByteBuffer.allocate(size);
buf.clear();
InetSocketAddress addr =
new InetSocketAddress(InetAddress.getLoopbackAddress(), 0);
// single send - same socket; different sockets
channel1 = DatagramChannel.open().bind(addr);
channel2 = DatagramChannel.open().bind(addr);
// connected read / write
connectedWriteChannel = DatagramChannel.open().bind(addr);
connectedReadChannel = DatagramChannel.open().bind(addr);
connectedWriteChannel.connect(connectedReadChannel.getLocalAddress());
connectedReadChannel.connect(connectedWriteChannel.getLocalAddress());
// multiple senders / multiple receivers
dca = new DatagramChannel[channelCount];
for (int i = 0; i < dca.length; i++) {
dca[i] = DatagramChannel.open().bind(addr);
}
multipleReceiveChannel = DatagramChannel.open().bind(addr);
multipleSendChannel = DatagramChannel.open().bind(addr);
}
// same sender receiver
@Benchmark
public void sendReceiveSingleSocket() throws IOException {
buf.clear();
channel1.send(buf, channel1.getLocalAddress());
buf.clear();
channel1.receive(buf);
}
// single sender, single receiver
@Benchmark
public void sendReceive() throws IOException {
buf.clear();
channel1.send(buf, channel2.getLocalAddress());
buf.clear();
channel2.receive(buf);
}
// connected sender receiver
@Benchmark
public void sendReceiveConnected() throws IOException {
buf.clear();
connectedWriteChannel.write(buf);
buf.clear();
connectedReadChannel.read(buf);
}
// multiple senders, single receiver
@Benchmark
public void sendMultiple() throws IOException {
int i = counter;
buf.clear();
dca[i].send(buf, multipleReceiveChannel.getLocalAddress());
buf.clear();
multipleReceiveChannel.receive(buf);
counter = ++i % dca.length;
}
// single sender, multiple receivers
@Benchmark
public void receiveMultiple() throws IOException {
int i = counter;
buf.clear();
multipleSendChannel.send(buf, dca[i].getLocalAddress());
buf.clear();
dca[i].receive(buf);
counter = ++i % dca.length;
}
@TearDown
public void tearDown() throws IOException {
channel1.close();
channel2.close();
connectedWriteChannel.close();
connectedReadChannel.close();
multipleReceiveChannel.close();
multipleSendChannel.close();
for (DatagramChannel dc : dca) {
dc.close();
}
}
}

View file

@ -0,0 +1,158 @@
/*
* Copyright (c) 2020, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import java.util.concurrent.TimeUnit;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
/**
* Benchmark DatagramSocket send/receive.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(3)
public class DatagramSocketSendReceive {
private int counter = 0;
private DatagramSocket socket1, socket2, connectedSendSocket,
connectedReceiveSocket, multipleRecieveSocket, multipleSendSocket;
private DatagramPacket sendPkt1, sendPkt2, connectedSendPkt, multipleSendPkt,
receivePkt;
private DatagramSocket[] dsa;
private DatagramPacket[] pkts;
@Param({"128", "32768"})
public int size;
@Param({"4"})
public int socketCount;
@Setup
public void setUp() throws IOException {
byte[] buf = new byte[size];
InetAddress addr = InetAddress.getLocalHost();
receivePkt = new DatagramPacket(buf, buf.length);
// single send - same socket; different sockets
socket1 = new DatagramSocket(0, addr);
socket2 = new DatagramSocket(0, addr);
sendPkt1 = new DatagramPacket(buf, buf.length, addr,
socket1.getLocalPort());
sendPkt2 = new DatagramPacket(buf, buf.length, addr,
socket2.getLocalPort());
// connected send/receive
connectedSendSocket = new DatagramSocket(0, addr);
connectedReceiveSocket = new DatagramSocket(0, addr);
connectedSendSocket.connect(addr, connectedReceiveSocket.getLocalPort());
connectedReceiveSocket.connect(addr, connectedSendSocket.getLocalPort());
connectedSendPkt = new DatagramPacket(buf, buf.length);
// multiple senders / multiple receivers
dsa = new DatagramSocket[socketCount];
pkts = new DatagramPacket[socketCount];
for (int i = 0; i < dsa.length; i++) {
dsa[i] = new DatagramSocket(0, addr);
pkts[i] = new DatagramPacket(buf, buf.length,
addr, dsa[i].getLocalPort());
}
multipleRecieveSocket = new DatagramSocket(0, addr);
multipleSendSocket = new DatagramSocket(0, addr);
multipleSendPkt = new DatagramPacket(buf, buf.length, addr,
multipleRecieveSocket.getLocalPort());
}
// same sender receiver
@Benchmark
public void sendReceiveSingleSocket() throws IOException {
socket1.send(sendPkt1);
socket1.receive(receivePkt);
}
// single sender, single receiver
@Benchmark
public void sendReceive() throws IOException {
socket1.send(sendPkt2);
socket2.receive(receivePkt);
}
// connected sender receiver
@Benchmark
public void sendReceiveConnected() throws IOException {
connectedSendSocket.send(connectedSendPkt);
connectedReceiveSocket.receive(receivePkt);
}
// multiple senders, single receiver
@Benchmark
public void sendMultiple() throws IOException {
int i = counter;
dsa[i].send(multipleSendPkt);
multipleRecieveSocket.receive(receivePkt);
counter = ++i % dsa.length;
}
// single sender, multiple receivers
@Benchmark
public void receiveMultiple() throws IOException {
int i = counter;
multipleSendSocket.send(pkts[i]);
dsa[i].receive(receivePkt);
counter = ++i % dsa.length;
}
@TearDown
public void tearDown() {
socket1.close();
socket2.close();
connectedSendSocket.close();
connectedReceiveSocket.close();
multipleRecieveSocket.close();
multipleSendSocket.close();
for (DatagramSocket ds : dsa) {
ds.close();
}
}
}

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2019, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.concurrent.TimeUnit;
/**
* Assess time to perform native NetworkInterface lookups; uses
* reflection to access both package-private isBoundInetAddress and
* public getByInetAddress (to get comparable numbers)
*/
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Fork(value = 2, jvmArgs = "--add-opens=java.base/java.net=ALL-UNNAMED")
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
public class NetworkInterfaceLookup {
static final InetAddress address = InetAddress.getLoopbackAddress();
static final Method isBoundInetAddress_method;
static final Method getByInetAddress_method;
static {
Method isBound = null;
Method getByInet = null;
try {
isBound = NetworkInterface.class.getDeclaredMethod("isBoundInetAddress", InetAddress.class);
isBound.setAccessible(true);
} catch (Exception e) {
System.out.println("NetworkInterface.isBoundInetAddress not found");
}
try {
getByInet = NetworkInterface.class.getDeclaredMethod("getByInetAddress", InetAddress.class);
} catch (Exception e) {
System.out.println("NetworkInterface.getByInetAddress not found");
}
isBoundInetAddress_method = isBound;
getByInetAddress_method = getByInet;
}
@Benchmark
public boolean bound() throws Exception {
return (boolean)isBoundInetAddress_method.invoke(null, address);
}
@Benchmark
public NetworkInterface getByInetAddress() throws Exception {
return (NetworkInterface)getByInetAddress_method.invoke(null, address);
}
}

View file

@ -0,0 +1,107 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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 org.openjdk.bench.java.net;
import java.io.IOException;
import java.net.StandardProtocolFamily;
import java.net.UnixDomainSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
/**
* Measures connection setup times
*/
@BenchmarkMode(Mode.SingleShotTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class SocketChannelConnectionSetup {
private ServerSocketChannel ssc;
private Path sscFilePath;
private SocketChannel s1, s2;
@Param({"INET", "UNIX"})
private String family;
@Setup(Level.Trial)
public void beforeRun() throws IOException {
StandardProtocolFamily typedFamily = StandardProtocolFamily.valueOf(family);
ssc = ServerSocketChannel.open(typedFamily).bind(null);
// Record the UDS file path right after binding, as the socket may be
// closed later due to a failure, and subsequent calls to `getPath()`
// will throw.
sscFilePath = ssc.getLocalAddress() instanceof UnixDomainSocketAddress udsChannel
? udsChannel.getPath()
: null;
}
@TearDown(Level.Trial)
public void afterRun() throws Exception {
ssc.close();
if (sscFilePath != null) {
Files.delete(sscFilePath);
}
}
@Benchmark
@Measurement(iterations = 5, batchSize=200)
public void test() throws IOException {
s1 = SocketChannel.open(ssc.getLocalAddress());
s2 = ssc.accept();
s1.close();
s2.close();
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(org.openjdk.bench.java.net.SocketChannelConnectionSetup.class.getSimpleName())
.warmupForks(1)
.forks(2)
.build();
new Runner(opt).run();
opt = new OptionsBuilder()
.include(org.openjdk.bench.java.net.SocketChannelConnectionSetup.class.getSimpleName())
.jvmArgs("-Djdk.net.useFastTcpLoopback=true")
.warmupForks(1)
.forks(2)
.build();
new Runner(opt).run();
}
}

View file

@ -0,0 +1,167 @@
/*
* Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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 org.openjdk.bench.java.net;
import jdk.internal.event.SocketReadEvent;
import jdk.internal.event.SocketWriteEvent;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
/**
* Test the overhead of the handling jfr events SocketReadEvent and
* SocketWriteEvent without the latencies of the actual I/O code.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS)
@State(Scope.Thread)
public class SocketEventOverhead {
@Fork(value = 1, jvmArgs = {
"--add-exports",
"java.base/jdk.internal.event=ALL-UNNAMED" })
@Benchmark
public int socketWriteJFRDisabled(SkeletonFixture fixture) {
return fixture.write();
}
@Fork(value = 1, jvmArgs = {
"--add-exports",
"java.base/jdk.internal.event=ALL-UNNAMED",
"-XX:StartFlightRecording:jdk.SocketWrite#enabled=false"})
@Benchmark
public int socketWriteJFREnabledEventDisabled(SkeletonFixture fixture) {
return fixture.write();
}
@Fork(value = 1, jvmArgs = {
"--add-exports",
"java.base/jdk.internal.event=ALL-UNNAMED",
"-XX:StartFlightRecording:jdk.SocketWrite#enabled=true,jdk.SocketWrite#threshold=1s,jdk.SocketWrite#throttle=off"})
@Benchmark
public int socketWriteJFREnabledEventNotEmitted(SkeletonFixture fixture) {
return fixture.write();
}
@Fork(value = 1, jvmArgs = {
"--add-exports","java.base/jdk.internal.event=ALL-UNNAMED",
"-XX:StartFlightRecording:jdk.SocketWrite#enabled=true,jdk.SocketWrite#threshold=0ms,disk=false,jdk.SocketWrite#stackTrace=false,jdk.SocketWrite#throttle=off"})
@Benchmark
public int socketWriteJFREnabledEventEmitted(SkeletonFixture fixture) {
return fixture.write();
}
@Fork(value = 1, jvmArgs = {
"--add-exports",
"java.base/jdk.internal.event=ALL-UNNAMED" })
@Benchmark
public int socketReadJFRDisabled(SkeletonFixture fixture) {
return fixture.read();
}
@Fork(value = 1, jvmArgs = {
"--add-exports",
"java.base/jdk.internal.event=ALL-UNNAMED",
"-XX:StartFlightRecording:jdk.SocketRead#enabled=false"})
@Benchmark
public int socketReadJFREnabledEventDisabled(SkeletonFixture fixture) {
return fixture.read();
}
@Fork(value = 1, jvmArgs = {
"--add-exports",
"java.base/jdk.internal.event=ALL-UNNAMED",
"-XX:StartFlightRecording:jdk.SocketRead#enabled=true,jdk.SocketRead#threshold=1s,jdk.SocketRead#throttle=off"})
@Benchmark
public int socketReadJFREnabledEventNotEmitted(SkeletonFixture fixture) {
return fixture.read();
}
@Fork(value = 1, jvmArgs = {
"--add-exports","java.base/jdk.internal.event=ALL-UNNAMED",
"-XX:StartFlightRecording:jdk.SocketRead#enabled=true,jdk.SocketRead#threshold=0ms,disk=false,jdk.SocketRead#stackTrace=false,jdk.SocketRead#throttle=off"})
@Benchmark
public int socketReadJFREnabledEventEmitted(SkeletonFixture fixture) {
return fixture.read();
}
/**
* Fixture with fake read/write operations that have only the JFR event
* boilerplate code for managing jfr events. No actual transfer is done
* to eliminate the I/O portion and measure the overhead of JFR event
* handling in it's various states.
*/
@State(Scope.Thread)
public static class SkeletonFixture {
private final InetSocketAddress remote = new InetSocketAddress("localhost",5000);
public SocketAddress getRemoteAddress() {
return remote;
}
public int write() {
if (! SocketWriteEvent.enabled()) {
return write0();
}
int nbytes = 0;
long start = SocketWriteEvent.timestamp();
try {
nbytes = write0();
} finally {
SocketWriteEvent.offer(start, nbytes, getRemoteAddress());
}
return nbytes;
}
private int write0() {
return 1024;
}
public int read() {
if (! SocketReadEvent.enabled()) {
return read0();
}
int nbytes = 0;
long start = SocketReadEvent.timestamp();
try {
nbytes = read0();
} finally {
SocketReadEvent.offer(start, nbytes, getRemoteAddress(), 0);
}
return nbytes;
}
private int read0() {
return 1024;
}
}
}

View file

@ -0,0 +1,221 @@
/*
* Copyright (c) 2014, 2019, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
/**
* Benchmark socket read/write.
*
*/
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@Warmup(iterations = 10, time = 1)
@Measurement(iterations = 5, time = 2)
@Fork(value = 3)
public class SocketReadWrite {
@Param({"1", "8192", "128000"})
public int size;
@Param({"false", "true"})
public boolean timeout;
static final InetAddress address = InetAddress.getLoopbackAddress();
public static final int TIMEOUT = 10000;
static class EchoServer implements Runnable {
// EchoServer is implemented to execute the same amount echo threads as benchmarking threads are running
final ServerSocket ss;
final int port;
final CountDownLatch startedLatch;
final int size;
final boolean timeout;
List<ServerThread> threads = new ArrayList<>();
volatile boolean isDone = false;
public EchoServer(CountDownLatch await, int size, boolean timeout) throws IOException {
this.size = size;
this.timeout = timeout;
ss = new ServerSocket(0);
port = ss.getLocalPort();
this.startedLatch = await;
}
@Override
public void run() {
startedLatch.countDown();
while (!isDone) {
try {
Socket s = ss.accept();
s.setTcpNoDelay(true);
if (timeout) {
s.setSoTimeout(TIMEOUT);
}
ServerThread st = new ServerThread(s, size);
threads.add(st);
new Thread(st).start();
} catch (IOException e) {
if (!isDone) {
e.printStackTrace();
}
}
}
}
synchronized void close() throws IOException {
if (!isDone) {
isDone = true;
ss.close();
for (ServerThread st : threads) {
st.close();
}
}
}
static EchoServer instance = null;
static synchronized EchoServer startServer(int size, boolean timeout) throws IOException {
if (instance == null) {
CountDownLatch started = new CountDownLatch(1);
EchoServer s = new EchoServer(started, size, timeout);
new Thread(s).start();
try {
started.await(); // wait until server thread started
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = s;
}
return instance;
}
static class ServerThread implements Runnable {
final Socket s;
final InputStream in;
final OutputStream out;
final int size;
volatile boolean isDone = false;
ServerThread(Socket s, int size) throws IOException {
this.s = s;
this.size = size;
in = s.getInputStream();
out = s.getOutputStream();
}
@Override
public void run() {
byte[] a = new byte[size];
while (!isDone) {
try {
readN(a, size, this.in);
out.write(a);
} catch (IOException e) {
if (!isDone) {
e.printStackTrace();
}
}
}
}
public void close() throws IOException {
isDone = true;
s.close();
}
}
}
static void readN(byte[] array, int size, InputStream in) throws IOException {
int nread = 0;
while (size > 0) {
int n = in.read(array, nread, size);
if (n < 0) throw new RuntimeException();
nread += n;
size -= n;
}
}
EchoServer server;
Socket s;
InputStream in;
OutputStream out;
byte[] array;
@Setup
public void setup() throws IOException {
server = EchoServer.startServer(size, timeout);
int port = server.port;
s = new Socket(address, port);
s.setTcpNoDelay(true);
if (timeout) {
s.setSoTimeout(TIMEOUT);
// 10 seconds times is quite large and never will happen (for microbenchmarking),
// but it's required since other paths inside SocketImpl are involved
}
in = s.getInputStream();
out = s.getOutputStream();
array = new byte[size];
ThreadLocalRandom.current().nextBytes(array);
}
@TearDown
public void tearDown() throws IOException {
server.close();
s.close();
}
@Benchmark
public void echo() throws IOException {
out.write(array);
readN(array, size, in);
}
}

View file

@ -0,0 +1,259 @@
/*
* Copyright (c) 2014, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.TimeUnit;
/**
* Micro benchmark for streaming data over a Socket.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class SocketStreaming {
/** The bytes to write/read. */
public static final int dataLength = 16383;
/** setTcpNoDelay(noNagle) */
public static final boolean noNagle = false;
private WriterThread writerThread;
private Socket readSocket;
private byte[] bytes;
@Setup
public void prepare() throws Exception {
bytes = new byte[dataLength];
// Setup the writer thread
writerThread = new WriterThread(dataLength, noNagle);
writerThread.start();
// Wait for a read socket
readSocket = writerThread.waitForReadSocket();
}
@TearDown
public void cleanup() throws IOException {
// Take down the writer thread and the reader socket
writerThread.finish();
while (!readSocket.isClosed()) {
readSocket.close();
}
readSocket = null;
}
@Benchmark
public void testSocketInputStreamRead() throws InterruptedException, IOException {
InputStream in = readSocket.getInputStream();
// Notify the writer thread to add elements to stream
writerThread.requestSendBytes();
// Read these from the stream
int bytesRead = 0;
while (bytesRead < dataLength) {
int lastRead = in.read(bytes);
if (lastRead < 0) {
throw new InternalError("Unexpectedly got " + lastRead + " bytes from the socket");
}
bytesRead += lastRead;
}
}
/**
* Thread used to write bytes to a socket.
*/
private class WriterThread extends Thread {
/** The number of bytes to write. */
private int dataLength;
/** setTcpNoDelay(noNagle) */
private boolean noNagle;
/** Lock needed to send sendBytes requests. */
private final Object sendBytesLock = new Object();
/** Indicates that a sendBytes has been requested. */
private boolean sendBytesRequested;
/** Indicates that no more sendBytes will be requested. Time to shutdown. */
private boolean sendBytesDone;
/** Lock needed to protect the connectPort variable. */
private final Object connectLock = new Object();
/** The port the read socket should connect to. */
private int connectPort = -1;
/**
* Constructor.
*
* @param dataLength The number of bytes to write
* @param noNagle setTcpNoDelay(noNagle)
*/
public WriterThread(int dataLength, boolean noNagle) {
super("Load producer");
this.dataLength = dataLength;
this.noNagle = noNagle;
}
/** Entry point for data sending helper thread. */
@Override
public void run() {
try {
Socket writeSocket;
ServerSocket serverSocket = new ServerSocket(0);
/* Tell the other thread that we now know the port number.
* The other thread will now start to connect until the following accept() call succeeds.
*/
synchronized (connectLock) {
connectPort = serverSocket.getLocalPort();
connectLock.notify();
}
// Wait for the other thread to connect
writeSocket = serverSocket.accept();
writeSocket.setTcpNoDelay(noNagle);
// No more connects so this can be closed
serverSocket.close();
serverSocket = null;
OutputStream out = writeSocket.getOutputStream();
// Iterate as long as sendBytes are issued
while (waitForSendBytesRequest()) {
sendBytes(out);
}
// Time to shutdown
while (!writeSocket.isClosed()) {
writeSocket.close();
}
writeSocket = null;
} catch (Exception e) {
System.exit(1);
}
}
/**
* Sends bytes to the output stream
*
* @param out The output stream
* @throws IOException
*/
private void sendBytes(OutputStream out) throws IOException {
byte outBytes[] = new byte[dataLength];
int bytesToSend = dataLength;
int bytesSent = 0;
while (bytesSent < bytesToSend) {
out.write(outBytes);
bytesSent += outBytes.length;
}
}
/**
* Waits for the readSocket and returns it when it is ready.
*
* @return The socket to read from
* @throws InterruptedException
*/
@SuppressWarnings("SleepWhileHoldingLock")
public Socket waitForReadSocket() throws InterruptedException {
int theConnectPort = waitForConnectPort();
while (true) {
try {
return new Socket(InetAddress.getByName(null), theConnectPort);
} catch (IOException e) {
// Wait some more for the server thread to get going
Thread.sleep(1000);
}
}
}
/**
* Waits for next sendBytes request
*
* @return <code>true</code> if it is time to sendBytes, <code>false</code> if it is time to shutdown
* @throws InterruptedException
*/
public boolean waitForSendBytesRequest() throws InterruptedException {
synchronized (sendBytesLock) {
while (!sendBytesRequested && !sendBytesDone) {
sendBytesLock.wait();
}
// Clear the flag
sendBytesRequested = false;
return !sendBytesDone;
}
}
/** Requests a sendBytes. */
public void requestSendBytes() {
synchronized (sendBytesLock) {
sendBytesRequested = true;
sendBytesLock.notify();
}
}
/** Tells the writerThread that it is time to shutdown. */
public void finish() {
synchronized (sendBytesLock) {
sendBytesDone = true;
sendBytesLock.notify();
}
}
private int waitForConnectPort() throws InterruptedException {
synchronized (connectLock) {
while (connectPort == -1) {
connectLock.wait();
}
return connectPort;
}
}
}
}

View file

@ -0,0 +1,79 @@
/*
* Copyright (c) 2020, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.CompilerControl;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.Warmup;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.net.URI;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import static java.lang.invoke.MethodType.methodType;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 1, jvmArgs = "--add-exports=java.base/sun.net.www=ALL-UNNAMED")
public class ThreadLocalParseUtil {
private static final MethodHandle MH_DECODE;
private static final MethodHandle MH_TO_URI;
static {
final MethodHandles.Lookup lookup = MethodHandles.lookup();
try {
Class<?> c = Class.forName("sun.net.www.ParseUtil");
MH_DECODE = lookup.findStatic(c, "decode", methodType(String.class, String.class));
MH_TO_URI = lookup.findStatic(c, "toURI", methodType(URI.class, URL.class));
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException e) {
throw new ExceptionInInitializerError(e);
}
}
@Benchmark
public String decodeTest() throws Throwable {
return (String) MH_DECODE.invokeExact("/xyz/\u00A0\u00A0");
}
@Benchmark
public URI appendEncodedTest() throws Throwable {
@SuppressWarnings("deprecation")
URL url = new URL("https://example.com/xyz/abc/def?query=#30");
return (URI) MH_TO_URI.invokeExact(url);
}
}

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2020, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.CompilerControl;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.TimeUnit;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class ThreadLocalURI {
@Benchmark
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public URI uriEncoderTest() throws URISyntaxException {
return new URI("http", "\u00A0", "\u00A0");
}
@Benchmark
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public URI uriDecoderBaseline() throws URISyntaxException {
return new URI("https", "example.com", "/xyz/abc/def?query=", "#30");
}
@Benchmark
@CompilerControl(CompilerControl.Mode.DONT_INLINE)
public String uriDecoderTest() throws URISyntaxException {
return new URI("https", "example.com", "/xyz/abc/def?query=", "#30")
.getPath();
}
}

View file

@ -0,0 +1,62 @@
/*
* Copyright Amazon.com Inc. 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import java.net.URI;
import java.util.concurrent.TimeUnit;
/**
* Tests Java.net.URI.create performance on various URI types.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class URIAuthorityParsingBenchmark {
@Param({
"https://98765432101.abc.xyz.com",
"https://ABCDEFGHIJK.abc.xyz.com"
})
private String uri;
@Benchmark
public void create(Blackhole blackhole) {
blackhole.consume(URI.create(uri));
}
}

View file

@ -0,0 +1,207 @@
/*
* Copyright (c) 2014, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Random;
import java.util.concurrent.TimeUnit;
/**
* Tests java.net.URLEncoder.encode and Decoder.decode.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class URLEncodeDecode {
private static final int COUNT = 1024;
@Param("1024")
public int maxLength;
/**
* Percentage of strings that will remain unchanged by an encoding/decoding (0-100)
*/
@Param({"0", "75", "100"})
public int unchanged;
/**
* Percentage of chars in changed strings that cause encoding/decoding to happen (0-100)
*/
@Param({"6"})
public int encodeChars;
public String[] testStringsEncode;
public String[] testStringsDecode;
public String[] toStrings;
@Setup()
public void setupStrings() {
char[] encodeTokens = new char[] { '[', '(', ' ', '\u00E4', '\u00E5', '\u00F6', ')', '='};
char[] tokens = new char[('Z' - 'A' + 1) + ('z' - 'a' + 1) + ('9' - '0' + 1) + 4];
int n = 0;
for (char c = '0'; c <= '9'; c++) {
tokens[n++] = c;
}
for (char c = 'A'; c <= 'Z'; c++) {
tokens[n++] = c;
}
for (char c = 'a'; c <= 'z'; c++) {
tokens[n++] = c;
}
tokens[n++] = '-';
tokens[n++] = '_';
tokens[n++] = '.';
tokens[n] = '*';
Random r = new Random(3);
testStringsEncode = new String[COUNT];
testStringsDecode = new String[COUNT];
toStrings = new String[COUNT];
for (int i = 0; i < COUNT; i++) {
int l = r.nextInt(maxLength);
boolean needEncoding = r.nextInt(100) >= unchanged;
StringBuilder sb = new StringBuilder();
boolean hasEncoded = false;
for (int j = 0; j < l; j++) {
if (needEncoding && r.nextInt(100) < encodeChars) {
addToken(encodeTokens, r, sb);
hasEncoded = true;
} else {
addToken(tokens, r, sb);
}
}
if (needEncoding && !hasEncoded) {
addToken(encodeTokens, r, sb);
}
testStringsEncode[i] = sb.toString();
}
int countUnchanged = 0;
for (String s : testStringsEncode) {
if (s.equals(java.net.URLEncoder.encode(s, StandardCharsets.UTF_8))) {
countUnchanged++;
} else {
if (unchanged == 100) {
System.out.println("Unexpectedly needs encoding action: ");
System.out.println("\t" + s);
System.out.println("\t" + java.net.URLEncoder.encode(s, StandardCharsets.UTF_8));
}
}
}
System.out.println();
System.out.println("Generated " + testStringsEncode.length + " encodable strings, " + countUnchanged + " of which does not need encoding action");
for (int i = 0; i < COUNT; i++) {
int l = r.nextInt(maxLength);
boolean needDecoding = r.nextInt(100) >= unchanged;
StringBuilder sb = new StringBuilder();
boolean hasDecoded = false;
for (int j = 0; j < l; j++) {
if (needDecoding && r.nextInt(100) < encodeChars) {
addDecodableChar(tokens, r, sb);
hasDecoded = true;
} else {
addToken(tokens, r, sb);
}
}
if (needDecoding && !hasDecoded) {
addDecodableChar(tokens, r, sb);
}
testStringsDecode[i] = sb.toString();
}
countUnchanged = 0;
for (String s : testStringsDecode) {
if (s.equals(java.net.URLDecoder.decode(s, StandardCharsets.UTF_8))) {
countUnchanged++;
} else {
if (unchanged == 100) {
System.out.println("Unexpectedly needs encoding action: ");
System.out.println("\t" + s);
System.out.println("\t" + java.net.URLDecoder.decode(s, StandardCharsets.UTF_8));
}
}
}
System.out.println("Generated " + testStringsDecode.length + " decodable strings, " + countUnchanged + " of which does not need decoding action");
}
private static void addToken(char[] tokens, Random r, StringBuilder sb) {
int c = r.nextInt(tokens.length);
sb.append(tokens[c]);
}
private static void addDecodableChar(char[] tokens, Random r, StringBuilder sb) {
if (r.nextInt(100) < 15) {
sb.append('+'); // exercise '+' -> ' ' decoding paths.
} else {
sb.append("%").append(tokens[r.nextInt(16)]).append(tokens[r.nextInt(16)]);
}
}
@Benchmark
public void testEncodeUTF8(Blackhole bh) throws UnsupportedEncodingException {
for (String s : testStringsEncode) {
bh.consume(java.net.URLEncoder.encode(s, StandardCharsets.UTF_8));
}
}
@Benchmark
public void testDecodeUTF8(Blackhole bh) throws UnsupportedEncodingException {
for (String s : testStringsDecode) {
bh.consume(URLDecoder.decode(s, StandardCharsets.UTF_8));
}
}
@Benchmark
public void testEncodeLatin1(Blackhole bh) throws UnsupportedEncodingException {
for (String s : testStringsEncode) {
bh.consume(java.net.URLEncoder.encode(s, StandardCharsets.ISO_8859_1));
}
}
@Benchmark
public void testDecodeLatin1(Blackhole bh) throws UnsupportedEncodingException {
for (String s : testStringsDecode) {
bh.consume(URLDecoder.decode(s, StandardCharsets.ISO_8859_1));
}
}
}

View file

@ -0,0 +1,77 @@
/*
* Copyright (c) 2026, 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.
*
* 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 org.openjdk.bench.java.net;
import org.openjdk.jmh.annotations.*;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.concurrent.TimeUnit;
/**
* Tests java.net.URL.toString performance
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class URLToString {
@Param({"false", "true"})
boolean auth;
@Param({"false", "true"})
boolean query;
@Param({"false", "true"})
boolean ref;
private URL url;
@Setup()
public void setup() throws MalformedURLException {
StringBuilder sb = new StringBuilder();
if (auth) {
sb.append("http://hostname");
} else {
sb.append("file:");
}
sb.append("/some/long/path/to/jar/app-1.0.jar!/org/summerframework/samples/horseclinic/HorseClinicApplication.class");
if (query) {
sb.append("?param=value");
}
if (ref) {
sb.append("#fragment");
}
url = URI.create(sb.toString()).toURL();
}
@Benchmark
public String urlToString() {
return url.toString();
}
}

View file

@ -0,0 +1,108 @@
/*
* Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* 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 org.openjdk.bench.java.net;
import java.io.IOException;
import java.net.StandardProtocolFamily;
import java.net.UnixDomainSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.*;
import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.*;
/**
* Tests the overheads of I/O API.
* This test is known to depend heavily on network conditions and paltform.
*/
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3)
public class UnixSocketChannelReadWrite {
private ServerSocketChannel ssc;
private Path sscFilePath;
private SocketChannel s1, s2;
private ReadThread rt;
private ByteBuffer bb = ByteBuffer.allocate(1);
@Setup(Level.Trial)
public void beforeRun() throws IOException {
ssc = ServerSocketChannel.open(StandardProtocolFamily.UNIX).bind(null);
// Record the UDS file path right after binding, as the socket may be
// closed later due to a failure, and subsequent calls to `getPath()`
// will throw.
sscFilePath = ((UnixDomainSocketAddress) ssc.getLocalAddress()).getPath();
s1 = SocketChannel.open(ssc.getLocalAddress());
s2 = ssc.accept();
rt = new ReadThread(s2);
rt.start();
bb.put((byte) 47);
bb.flip();
}
@TearDown(Level.Trial)
public void afterRun() throws IOException, InterruptedException {
s1.close();
s2.close();
ssc.close();
Files.delete(sscFilePath);
rt.join();
}
@Benchmark
public void test() throws IOException {
s1.write(bb);
bb.flip();
}
static class ReadThread extends Thread {
private SocketChannel sc;
public ReadThread(SocketChannel s2) {
this.sc = s2;
}
public void run() {
try {
ByteBuffer bb = ByteBuffer.allocate(1);
while (sc.read(bb) > 0) {
bb.flip();
}
} catch (ClosedChannelException ex) {
// shutdown time
} catch (IOException e) {
e.printStackTrace();
}
}
}
}