Summary
Replace the underlying implementation used by the java.net.DatagramSocket
and java.net.MulticastSocket
APIs with a simpler and more modern implementation that are easier to maintain and debug. The new implementation will be easy to adapt to work with virtual threads, currently being explored in Project Loom. This is a follow-on to JEP 353, which already reimplemented the legacy Socket
API.
Problem
The java.net.DatagramSocket
and java.net.MulticastSocket
APIs, and their underlying implementation, date back to JDK 1.0. The implementation is a mix of legacy Java and C code that is painful to maintain and debug. In the context of a future world of virtual threads that park instead of block underlying kernel threads in system calls, the current implementation is not fit for purpose. As datagram-based transports gain traction again (e.g. QUIC), a simpler and more maintainable implementation is needed.
Solution
Currently, the DatagramSocket
and MulticastSocket
classes delegate all socket calls to a java.net.DatagramSocketImpl
implementation, for which different platform-specific concrete implementations exist: PlainDatagramSocketImpl
on Unix platforms, and TwoStackPlainDatagramSocketImpl
and DualPlainDatagramSocketImpl
on Windows platforms.
Rather than provide a drop-in replacement for implementations of DatagramSocketImpl
, similar to what was done in JEP 353 for SocketImpl
, this JEP proposes to make DatagramSocket
internally wrap another instance of DatagramSocket
to which it delegates all calls directly. The wrapped instance is either a socket adapter created from a NIO DatagramChannel::socket
(the new implementation), or else a clone of the legacy DatagramSocket
class which then delegates to the legacy DatagramSocketImpl
implementation (for the purpose of implementing a backward compatibility switch). If a DatagramSocketImplFactory
is installed by an application, the old legacy implementation is selected. Otherwise, the new implementation is selected and used by default. To reduce the risk of switching the implementation after more than twenty years, the legacy implementation will not be removed.
Specification
There are no Java SE specification changes. Some preparatory work to clarify the specifications of DatagramSocket
and MulticastSocket
, and to minimize the behavioral differences between these classes and the DatagramChannel::socket
adapter, has already been done in JDK 14 and JDK 15, such as JDK-8222829, JDK-8233191, etc.
A JDK-specific system property, jdk.net.usePlainDatagramSocketImpl
, is introduced to configure the JDK to use the legacy implementation. If set with no value or set to the value "true" at startup, the legacy implementation is used. Otherwise, the new (NIO-based) implementation is used. The new implementation is enabled by default. It provides non-interruptible behavior for datagram and multicast sockets by directly using the platform-default implementation of the selector provider (sun.nio.ch.SelectorProviderImpl
and sun.nio.ch.DatagramChannelImpl
). Installing a custom selector provider will thus have no effect on DatagramSocket
and MulticastSocket
.
In addition, an implementation note will be added to the DatagramSocketImpl
class description:
/**
* Abstract datagram and multicast socket implementation base class.
+ *
+ * @implNote Sockets created with the {@code DatagramSocket} and {@code
+ * MulticastSocket} public constructors historically delegated all socket
+ * operations to a {@code DatagramSocketImpl} implementation named
+ * "PlainDatagramSocketImpl". {@code DatagramSocket} and {@code MulticastSocket}
+ * have since been changed to a new implementation based on {@code DatagramChannel}.
+ * The JDK continues to ship with the older implementation to allow code to run
+ * that depends on unspecified behavior that differs between the old and new
+ * implementations. The old implementation will be used if the Java virtual
+ * machine is started with the system property {@systemProperty
+ * jdk.net.usePlainDatagramSocketImpl} set to use the old implementation. It may
+ * also be set in the JDK's network configuration file, located in {@code
+ * ${java.home}/conf/net.properties}. The value of the property is the string
+ * representation of a boolean. If set without a value then it defaults to {@code
+ * true}, hence running with {@code -Djdk.net.usePlainDatagramSocketImpl} or
+ * {@code -Djdk.net.usePlainDatagramSocketImpl=true} will configure the Java
+ * virtual machine to use the old implementation. The property and old
+ * implementation will be removed in a future version.
+ *
* @author Pavani Diwanji
* @since 1.1
*/
- csr of
-
JDK-8241072 Reimplement the Legacy DatagramSocket API
- Resolved