Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8356225

Respecify java.net.Socket constructors that allow creating UDP sockets to throw IllegalArgumentException

XMLWordPrintable

    • Icon: CSR CSR
    • Resolution: Approved
    • Icon: P4 P4
    • 25
    • core-libs
    • None
    • behavioral
    • minimal
    • Hide
      Corpus analysis was done to check if there are sub-classes of Socket which do anything useful/different with stream=false in their constructors. There weren't many sub-classes of Socket and of the few that were found, they either just passed the stream as-is to the super(...) or threw an exception if stream was false. The fact that some external sub-classes already throw an exception for stream=false is a sign that the deprecation (since Java 1.1) has already been noticed.
      For the changes to SocketImpl class, not many sub-classes of that class are expected to be around. The proposed changes to SocketImpl will not break those existing implementations.
      Given this, the compatibility risk of this change is expected to be minimal.
      Show
      Corpus analysis was done to check if there are sub-classes of Socket which do anything useful/different with stream=false in their constructors. There weren't many sub-classes of Socket and of the few that were found, they either just passed the stream as-is to the super(...) or threw an exception if stream was false. The fact that some external sub-classes already throw an exception for stream=false is a sign that the deprecation (since Java 1.1) has already been noticed. For the changes to SocketImpl class, not many sub-classes of that class are expected to be around. The proposed changes to SocketImpl will not break those existing implementations. Given this, the compatibility risk of this change is expected to be minimal.
    • Java API
    • SE

      Summary

      The specification of the following 2 constructors of java.net.Socket are changed to throw java.lang.IllegalArgumentException when called to create a datagram socket (stream == false).

      public Socket(InetAddress host, int port, boolean stream)
      public Socket(String host, int port, boolean stream)
      

      Problem

      Socket class has allowed for constructing TCP sockets as well as UDP sockets. There are 2 constructors in this class which take a boolean stream parameter to indicate whether the socket is TCP or UDP. stream value of false implies a UDP socket.

      These 2 constructors have been deprecated long back since Java 1.1. Very recently in Java 23, these constructors have been deprecated for removal https://bugs.openjdk.org/browse/JDK-8333092. These constructors will eventually be removed in a future release.

      Although the usage of these 2 constructors has been very low, it would be good to make this change more visible and prominent to applications and libraries, before they are removed.

      Furthermore, Socket implementation allows for custom socket implementations when creating the socket. The public API java.net.SocketImpl.create(boolean):

      protected abstract void create(boolean stream) throws IOException;

      is invoked on the custom socket implementation class' instance through the Socket constructors. Applications and libraries can have sub-class for SocketImpl, whose create(...) method will be invoked by the Socket constructors. With this proposal to respecify the 2 constructors of Socket, it now means that these Socket constructors will no longer call the SocketImpl.create(...) with stream as false.

      Solution

      The 2 Socket constructors will be respecified to throw an IllegalArgumentException if stream parameter is false.

      Additionally, SocketImpl.create(...) method will be respecified and its current @apiNote will be updated to mention that the Socket constructors will always call it with stream as true.

      Specification

      diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java
      -     * If the stream argument is {@code true}, this creates a
      -     * stream socket. If the stream argument is {@code false}, it
      -     * creates a datagram socket.
      -     * <p>
            * If the application has specified a {@linkplain SocketImplFactory client
            * socket implementation factory}, that factory's
            * {@linkplain SocketImplFactory#createSocketImpl() createSocketImpl}
            * method is called to create the actual socket implementation. Otherwise
            * a system-default socket implementation is created.
      -     * <p>
      -     * If a UDP socket is used, TCP/IP related socket options will not apply.
            *
            * @param      host     the host name, or {@code null} for the loopback address.
            * @param      port     the port number.
      -     * @param      stream   a {@code boolean} indicating whether this is
      -     *                      a stream socket or a datagram socket.
      +     * @param      stream   must be true, false is not allowed.
            * @throws     IOException  if an I/O error occurs when creating the socket.
      -     * @throws     IllegalArgumentException if the port parameter is outside
      -     *             the specified range of valid port values, which is between
      -     *             0 and 65535, inclusive.
      -     * @deprecated Use {@link DatagramSocket} instead for UDP transport.
      +     * @throws     IllegalArgumentException if the stream parameter is {@code false}
      +     *             or if the port parameter is outside the specified range of valid
      +     *             port values, which is between 0 and 65535, inclusive.
      +     * @deprecated The {@code stream} parameter provided a way in early JDK releases
      +     *             to create a {@code Socket} that used a datagram socket. This feature
      +     *             no longer exists. Instead use {@link DatagramSocket} for datagram sockets.
            */
           @Deprecated(forRemoval = true, since = "1.1")
           @SuppressWarnings("this-escape")
           public Socket(String host, int port, boolean stream) throws IOException {
      -     * If the stream argument is {@code true}, this creates a
      -     * stream socket. If the stream argument is {@code false}, it
      -     * creates a datagram socket.
      -     * <p>
            * If the application has specified a {@linkplain SocketImplFactory client
            * socket implementation factory}, that factory's
            * {@linkplain SocketImplFactory#createSocketImpl() createSocketImpl}
            * method is called to create the actual socket implementation. Otherwise
            * a system-default socket implementation is created.
      -     * <p>
      -     * If UDP socket is used, TCP/IP related socket options will not apply.
            *
            * @param      host     the IP address.
            * @param      port      the port number.
      -     * @param      stream    if {@code true}, create a stream socket;
      -     *                       otherwise, create a datagram socket.
      +     * @param      stream    must be true, false is not allowed.
            * @throws     IOException  if an I/O error occurs when creating the socket.
      -     * @throws     IllegalArgumentException if the port parameter is outside
      -     *             the specified range of valid port values, which is between
      -     *             0 and 65535, inclusive.
      +     * @throws     IllegalArgumentException if the stream parameter is {@code false}
      +     *             or if the port parameter is outside the specified range of valid
      +     *             port values, which is between 0 and 65535, inclusive.
            * @throws     NullPointerException if {@code host} is null.
      -     * @deprecated Use {@link DatagramSocket} instead for UDP transport.
      +     * @deprecated The {@code stream} parameter provided a way in early JDK releases
      +     *             to create a {@code Socket} that used a datagram socket. This feature
      +     *             no longer exists. Instead use {@link DatagramSocket} for datagram sockets.
            */
           @Deprecated(forRemoval = true, since = "1.1")
           @SuppressWarnings("this-escape")
           public Socket(InetAddress host, int port, boolean stream) throws IOException
      diff --git a/src/java.base/share/classes/java/net/SocketImpl.java b/src/java.base/share/classes/java/net/SocketImpl.java
           /**
      -     * Creates either a stream or a datagram socket.
      +     * Creates a stream socket.
            *
            * @apiNote
      -     * The {@link Socket} constructors to create a datagram socket
      -     * are deprecated for removal. This method will be re-specified
      -     * in a future release to not support creating datagram sockets.
      +     * The {@code stream} parameter provided a way in early JDK releases
      +     * to create a {@link Socket} that used a datagram socket.
      +     * The Socket API no longer provides a way to do this, so the
      +     * {@code create} method will always be called with a {@code stream}
      +     * value of {@code true}.
            *
      -     * @param      stream   if {@code true}, create a stream socket;
      -     *                      otherwise, create a datagram socket.
      +     * @param      stream   must be {@code true}.
            * @throws     IOException  if an I/O error occurs while creating the
            *               socket.
            */
            protected abstract void create(boolean stream) throws IOException;

            jpai Jaikiran Pai
            jpai Jaikiran Pai
            Alan Bateman
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: