8216978: Drop support for pre JDK 1.4 SocketImpl implementations
authormichaelm
Thu, 02 May 2019 17:29:10 +0100
changeset 54689 b28b7f631301
parent 54688 96ad739cfc39
child 54690 7ab4310ed472
child 54868 88b769ae99c7
8216978: Drop support for pre JDK 1.4 SocketImpl implementations Reviewed-by: chegar, alanb, dfuchs
src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
src/java.base/share/classes/java/net/HttpConnectSocketImpl.java
src/java.base/share/classes/java/net/ServerSocket.java
src/java.base/share/classes/java/net/Socket.java
src/java.base/share/classes/java/net/SocketImpl.java
src/java.base/share/classes/java/net/SocketInputStream.java
src/java.base/share/classes/java/net/SocketOutputStream.java
src/java.base/share/classes/java/net/SocksSocketImpl.java
src/java.base/unix/classes/java/net/PlainSocketImpl.java
src/java.base/unix/native/libnet/PlainSocketImpl.c
src/java.base/windows/classes/java/net/PlainSocketImpl.java
test/jdk/java/net/Socket/OldImpl.java
test/jdk/java/net/Socket/OldSocketImpl.java
test/jdk/java/net/Socket/OldSocketImplTest.java
test/jdk/java/net/Socket/OldSocketImplTestDriver.java
--- a/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Thu May 02 17:29:10 2019 +0100
@@ -74,6 +74,12 @@
     /* indicates connection reset state */
     private volatile boolean connectionReset;
 
+    /* indicates whether impl is bound  */
+    boolean isBound;
+
+    /* indicates whether impl is connected  */
+    volatile boolean isConnected;
+
    /* whether this Socket is a stream (TCP) socket or not (UDP)
     */
     protected boolean stream;
@@ -105,6 +111,10 @@
         return isReusePortAvailable;
     }
 
+    AbstractPlainSocketImpl(boolean isServer) {
+        super(isServer);
+    }
+
     /**
      * Returns a set of SocketOptions supported by this impl and by this impl's
      * socket (Socket or ServerSocket)
@@ -148,10 +158,6 @@
             socketCreate(true);
             SocketCleanable.register(fd);
         }
-        if (socket != null)
-            socket.setCreated();
-        if (serverSocket != null)
-            serverSocket.setCreated();
     }
 
     /**
@@ -180,6 +186,7 @@
                        it will be passed up the call stack */
                 }
             }
+            isConnected = connected;
         }
     }
 
@@ -195,6 +202,7 @@
 
         try {
             connectToAddress(address, port, timeout);
+            isConnected = true;
             return;
         } catch (IOException e) {
             // everything failed
@@ -236,6 +244,7 @@
                        it will be passed up the call stack */
                 }
             }
+            isConnected = connected;
         }
     }
 
@@ -393,7 +402,7 @@
 
     synchronized void doConnect(InetAddress address, int port, int timeout) throws IOException {
         synchronized (fdLock) {
-            if (!closePending && (socket == null || !socket.isBound())) {
+            if (!closePending && !isBound) {
                 NetHooks.beforeTcpConnect(fd, address, port);
             }
         }
@@ -407,14 +416,6 @@
                         throw new SocketException ("Socket closed");
                     }
                 }
-                // If we have a ref. to the Socket, then sets the flags
-                // created, bound & connected to true.
-                // This is normally done in Socket.connect() but some
-                // subclasses of Socket may call impl.connect() directly!
-                if (socket != null) {
-                    socket.setBound();
-                    socket.setConnected();
-                }
             } finally {
                 releaseFD();
             }
@@ -433,15 +434,12 @@
         throws IOException
     {
        synchronized (fdLock) {
-            if (!closePending && (socket == null || !socket.isBound())) {
+            if (!closePending && !isBound) {
                 NetHooks.beforeTcpBind(fd, address, lport);
             }
         }
         socketBind(address, lport);
-        if (socket != null)
-            socket.setBound();
-        if (serverSocket != null)
-            serverSocket.setBound();
+        isBound = true;
     }
 
     /**
@@ -727,7 +725,7 @@
         socketClose0(false);
     }
 
-    abstract void socketCreate(boolean isServer) throws IOException;
+    abstract void socketCreate(boolean stream) throws IOException;
     abstract void socketConnect(InetAddress address, int port, int timeout)
         throws IOException;
     abstract void socketBind(InetAddress address, int port)
--- a/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/HttpConnectSocketImpl.java	Thu May 02 17:29:10 2019 +0100
@@ -51,6 +51,7 @@
     private static final Method doTunneling;
 
     private final String server;
+    private final Socket socket;
     private InetSocketAddress external_address;
     private HashMap<Integer, Object> optionsMap = new HashMap<>();
 
@@ -75,8 +76,9 @@
         }
     }
 
-    HttpConnectSocketImpl(Proxy proxy, SocketImpl delegate) {
+    HttpConnectSocketImpl(Proxy proxy, SocketImpl delegate, Socket socket) {
         super(delegate);
+        this.socket = socket;
         SocketAddress a = proxy.address();
         if ( !(a instanceof InetSocketAddress) )
             throw new IllegalArgumentException("Unsupported address type");
@@ -97,17 +99,6 @@
     }
 
     @Override
-    void setSocket(Socket socket) {
-        delegate.socket = socket;
-        super.setSocket(socket);
-    }
-
-    @Override
-    void setServerSocket(ServerSocket socket) {
-        throw new InternalError("should not get here");
-    }
-
-    @Override
     protected void connect(SocketAddress endpoint, int timeout)
         throws IOException
     {
@@ -137,7 +128,7 @@
 
         // update the Sockets impl to the impl from the http Socket
         SocketImpl si = httpSocket.impl;
-        getSocket().setImpl(si);
+        socket.setImpl(si);
 
         // best effort is made to try and reset options previously set
         Set<Map.Entry<Integer,Object>> options = optionsMap.entrySet();
--- a/src/java.base/share/classes/java/net/ServerSocket.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/ServerSocket.java	Thu May 02 17:29:10 2019 +0100
@@ -72,11 +72,6 @@
     private SocketImpl impl;
 
     /**
-     * Are we using an older SocketImpl?
-     */
-    private boolean oldImpl = false;
-
-    /**
      * Creates a server socket with a user-specified {@code SocketImpl}.
      *
      * @param      impl an instance of a SocketImpl to use on the ServerSocket.
@@ -87,7 +82,6 @@
      */
     protected ServerSocket(SocketImpl impl) {
         this.impl = impl;
-        impl.setServerSocket(this);
     }
 
     /**
@@ -270,36 +264,13 @@
         return impl;
     }
 
-    private void checkOldImpl() {
-        if (impl == null)
-            return;
-        // SocketImpl.connect() is a protected method, therefore we need to use
-        // getDeclaredMethod, therefore we need permission to access the member
-        try {
-            AccessController.doPrivileged(
-                new PrivilegedExceptionAction<Void>() {
-                    public Void run() throws NoSuchMethodException {
-                        impl.getClass().getDeclaredMethod("connect",
-                                                          SocketAddress.class,
-                                                          int.class);
-                        return null;
-                    }
-                });
-        } catch (java.security.PrivilegedActionException e) {
-            oldImpl = true;
-        }
-    }
-
     private void setImpl() {
         SocketImplFactory factory = ServerSocket.factory;
         if (factory != null) {
             impl = factory.createSocketImpl();
-            checkOldImpl();
         } else {
             impl = SocketImpl.createPlatformSocketImpl(true);
         }
-        if (impl != null)
-            impl.setServerSocket(this);
     }
 
     /**
@@ -368,7 +339,7 @@
     public void bind(SocketAddress endpoint, int backlog) throws IOException {
         if (isClosed())
             throw new SocketException("Socket is closed");
-        if (!oldImpl && isBound())
+        if (isBound())
             throw new SocketException("Already bound");
         if (endpoint == null)
             endpoint = new InetSocketAddress(0);
@@ -722,8 +693,7 @@
      * @since 1.4
      */
     public boolean isBound() {
-        // Before 1.3 ServerSockets were always bound during creation
-        return bound || oldImpl;
+        return bound;
     }
 
     /**
@@ -866,14 +836,6 @@
                 ",localport=" + impl.getLocalPort()  + "]";
     }
 
-    void setBound() {
-        bound = true;
-    }
-
-    void setCreated() {
-        created = true;
-    }
-
     /**
      * The factory for all server sockets.
      */
--- a/src/java.base/share/classes/java/net/Socket.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/Socket.java	Thu May 02 17:29:10 2019 +0100
@@ -72,11 +72,6 @@
     SocketImpl impl;
 
     /**
-     * Are we using an older SocketImpl?
-     */
-    private boolean oldImpl = false;
-
-    /**
      * Socket input/output streams
      */
     private volatile InputStream in;
@@ -158,8 +153,7 @@
             // create a SOCKS or HTTP SocketImpl that delegates to a platform SocketImpl
             SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
             impl = (type == Proxy.Type.SOCKS) ? new SocksSocketImpl(p, delegate)
-                                              : new HttpConnectSocketImpl(p, delegate);
-            impl.setSocket(this);
+                                              : new HttpConnectSocketImpl(p, delegate, this);
         } else {
             if (p == Proxy.NO_PROXY) {
                 // create a platform or custom SocketImpl for the DIRECT case
@@ -169,7 +163,6 @@
                 } else {
                     impl = factory.createSocketImpl();
                 }
-                impl.setSocket(this);
             } else
                 throw new IllegalArgumentException("Invalid Proxy");
         }
@@ -188,10 +181,6 @@
      */
     protected Socket(SocketImpl impl) throws SocketException {
         this.impl = impl;
-        if (impl != null) {
-            checkOldImpl();
-            this.impl.setSocket(this);
-        }
     }
 
     /**
@@ -486,37 +475,8 @@
         }
     }
 
-    private void checkOldImpl() {
-        if (impl == null)
-            return;
-        // SocketImpl.connect() is a protected method, therefore we need to use
-        // getDeclaredMethod, therefore we need permission to access the member
-
-        oldImpl = AccessController.doPrivileged
-                                (new PrivilegedAction<>() {
-            public Boolean run() {
-                Class<?> clazz = impl.getClass();
-                while (true) {
-                    try {
-                        clazz.getDeclaredMethod("connect", SocketAddress.class, int.class);
-                        return Boolean.FALSE;
-                    } catch (NoSuchMethodException e) {
-                        clazz = clazz.getSuperclass();
-                        // java.net.SocketImpl class will always have this abstract method.
-                        // If we have not found it by now in the hierarchy then it does not
-                        // exist, we are an old style impl.
-                        if (clazz.equals(java.net.SocketImpl.class)) {
-                            return Boolean.TRUE;
-                        }
-                    }
-                }
-            }
-        });
-    }
-
     void setImpl(SocketImpl si) {
          impl = si;
-         impl.setSocket(this);
     }
 
     /**
@@ -527,14 +487,11 @@
         SocketImplFactory factory = Socket.factory;
         if (factory != null) {
             impl = factory.createSocketImpl();
-            checkOldImpl();
         } else {
             // create a SOCKS SocketImpl that delegates to a platform SocketImpl
             SocketImpl delegate = SocketImpl.createPlatformSocketImpl(false);
             impl = new SocksSocketImpl(delegate);
         }
-        if (impl != null)
-            impl.setSocket(this);
     }
 
     /**
@@ -596,7 +553,7 @@
         if (isClosed())
             throw new SocketException("Socket is closed");
 
-        if (!oldImpl && isConnected())
+        if (isConnected())
             throw new SocketException("already connected");
 
         if (!(endpoint instanceof InetSocketAddress))
@@ -616,15 +573,7 @@
         }
         if (!created)
             createImpl(true);
-        if (!oldImpl)
-            impl.connect(epoint, timeout);
-        else if (timeout == 0) {
-            if (epoint.isUnresolved())
-                impl.connect(addr.getHostName(), port);
-            else
-                impl.connect(addr, port);
-        } else
-            throw new UnsupportedOperationException("SocketImpl.connect(addr, timeout)");
+        impl.connect(epoint, timeout);
         connected = true;
         /*
          * If the socket was not bound before the connect, it is now because
@@ -654,7 +603,7 @@
     public void bind(SocketAddress bindpoint) throws IOException {
         if (isClosed())
             throw new SocketException("Socket is closed");
-        if (!oldImpl && isBound())
+        if (isBound())
             throw new SocketException("Already bound");
 
         if (bindpoint != null && (!(bindpoint instanceof InetSocketAddress)))
@@ -694,18 +643,6 @@
         bound = true;
     }
 
-    void setCreated() {
-        created = true;
-    }
-
-    void setBound() {
-        bound = true;
-    }
-
-    void setConnected() {
-        connected = true;
-    }
-
     /**
      * Returns the address to which the socket is connected.
      * <p>
@@ -957,6 +894,7 @@
     private static class SocketInputStream extends InputStream {
         private final Socket parent;
         private final InputStream in;
+
         SocketInputStream(Socket parent, InputStream in) {
             this.parent = parent;
             this.in = in;
@@ -975,6 +913,7 @@
         public int available() throws IOException {
             return in.available();
         }
+
         @Override
         public void close() throws IOException {
             parent.close();
@@ -1040,6 +979,7 @@
         public void write(byte b[], int off, int len) throws IOException {
             out.write(b, off, len);
         }
+
         @Override
         public void close() throws IOException {
             parent.close();
@@ -1672,8 +1612,7 @@
      * @since 1.4
      */
     public boolean isConnected() {
-        // Before 1.3 Sockets were always connected during creation
-        return connected || oldImpl;
+        return connected;
     }
 
     /**
@@ -1689,8 +1628,7 @@
      * @see #bind
      */
     public boolean isBound() {
-        // Before 1.3 Sockets were always bound during creation
-        return bound || oldImpl;
+        return bound;
     }
 
     /**
--- a/src/java.base/share/classes/java/net/SocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocketImpl.java	Thu May 02 17:29:10 2019 +0100
@@ -51,16 +51,10 @@
      */
     @SuppressWarnings("unchecked")
     static <S extends SocketImpl & PlatformSocketImpl> S createPlatformSocketImpl(boolean server) {
-        return (S) new PlainSocketImpl();
+        return (S) new PlainSocketImpl(server);
     }
 
     /**
-     * The actual Socket object.
-     */
-    Socket socket = null;
-    ServerSocket serverSocket = null;
-
-    /**
      * The file descriptor object for this socket.
      */
     protected FileDescriptor fd;
@@ -81,6 +75,23 @@
     protected int localport;
 
     /**
+     * Whether this is a server or not.
+     */
+    final boolean isServer;
+
+
+    SocketImpl(boolean isServer) {
+        this.isServer = isServer;
+    }
+
+    /**
+     * Initialize a new instance of this class
+     */
+    public SocketImpl() {
+        this.isServer = false;
+    }
+
+    /**
      * Creates either a stream or a datagram socket.
      *
      * @param      stream   if {@code true}, create a stream socket;
@@ -300,22 +311,6 @@
         return localport;
     }
 
-    void setSocket(Socket soc) {
-        this.socket = soc;
-    }
-
-    Socket getSocket() {
-        return socket;
-    }
-
-    void setServerSocket(ServerSocket soc) {
-        this.serverSocket = soc;
-    }
-
-    ServerSocket getServerSocket() {
-        return serverSocket;
-    }
-
     /**
      * Returns the address and port of this socket as a {@code String}.
      *
@@ -395,11 +390,9 @@
      * @since 9
      */
     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
-        if (name == StandardSocketOptions.SO_KEEPALIVE &&
-                (getSocket() != null)) {
+        if (name == StandardSocketOptions.SO_KEEPALIVE && !isServer) {
             setOption(SocketOptions.SO_KEEPALIVE, value);
-        } else if (name == StandardSocketOptions.SO_SNDBUF &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_SNDBUF && !isServer) {
             setOption(SocketOptions.SO_SNDBUF, value);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             setOption(SocketOptions.SO_RCVBUF, value);
@@ -408,13 +401,11 @@
         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
             supportedOptions().contains(name)) {
             setOption(SocketOptions.SO_REUSEPORT, value);
-        } else if (name == StandardSocketOptions.SO_LINGER &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_LINGER && !isServer) {
             setOption(SocketOptions.SO_LINGER, value);
         } else if (name == StandardSocketOptions.IP_TOS) {
             setOption(SocketOptions.IP_TOS, value);
-        } else if (name == StandardSocketOptions.TCP_NODELAY &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.TCP_NODELAY && !isServer) {
             setOption(SocketOptions.TCP_NODELAY, value);
         } else {
             throw new UnsupportedOperationException("unsupported option");
@@ -438,11 +429,9 @@
      */
     @SuppressWarnings("unchecked")
     protected <T> T getOption(SocketOption<T> name) throws IOException {
-        if (name == StandardSocketOptions.SO_KEEPALIVE &&
-                (getSocket() != null)) {
+        if (name == StandardSocketOptions.SO_KEEPALIVE && !isServer) {
             return (T)getOption(SocketOptions.SO_KEEPALIVE);
-        } else if (name == StandardSocketOptions.SO_SNDBUF &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_SNDBUF && !isServer) {
             return (T)getOption(SocketOptions.SO_SNDBUF);
         } else if (name == StandardSocketOptions.SO_RCVBUF) {
             return (T)getOption(SocketOptions.SO_RCVBUF);
@@ -451,13 +440,11 @@
         } else if (name == StandardSocketOptions.SO_REUSEPORT &&
             supportedOptions().contains(name)) {
             return (T)getOption(SocketOptions.SO_REUSEPORT);
-        } else if (name == StandardSocketOptions.SO_LINGER &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.SO_LINGER && !isServer) {
             return (T)getOption(SocketOptions.SO_LINGER);
         } else if (name == StandardSocketOptions.IP_TOS) {
             return (T)getOption(SocketOptions.IP_TOS);
-        } else if (name == StandardSocketOptions.TCP_NODELAY &&
-                (getSocket() != null)) {
+        } else if (name == StandardSocketOptions.TCP_NODELAY && !isServer) {
             return (T)getOption(SocketOptions.TCP_NODELAY);
         } else {
             throw new UnsupportedOperationException("unsupported option");
@@ -504,7 +491,7 @@
      * @since 9
      */
     protected Set<SocketOption<?>> supportedOptions() {
-        if (getSocket() != null) {
+        if (!isServer) {
             return socketOptions;
         } else {
             return serverSocketOptions;
--- a/src/java.base/share/classes/java/net/SocketInputStream.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocketInputStream.java	Thu May 02 17:29:10 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -48,7 +48,6 @@
     private boolean eof;
     private AbstractPlainSocketImpl impl = null;
     private byte temp[];
-    private Socket socket = null;
 
     /**
      * Creates a new SocketInputStream. Can only be called
@@ -59,7 +58,6 @@
     SocketInputStream(AbstractPlainSocketImpl impl) throws IOException {
         super(impl.getFileDescriptor());
         this.impl = impl;
-        socket = impl.getSocket();
     }
 
     /**
@@ -236,25 +234,14 @@
         return eof ? 0 : available;
     }
 
-    /**
-     * Closes the stream.
-     */
-    private boolean closing = false;
-    public void close() throws IOException {
-        // Prevent recursion. See BugId 4484411
-        if (closing)
-            return;
-        closing = true;
-        if (socket != null) {
-            if (!socket.isClosed())
-                socket.close();
-        } else
-            impl.close();
-        closing = false;
+    void setEOF(boolean eof) {
+        this.eof = eof;
     }
 
-    void setEOF(boolean eof) {
-        this.eof = eof;
+    public void close() throws IOException {
+        // No longer used. Socket.getInputStream returns an
+        // InputStream which calls Socket.close directly
+        assert false;
     }
 
     /**
--- a/src/java.base/share/classes/java/net/SocketOutputStream.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocketOutputStream.java	Thu May 02 17:29:10 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 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
@@ -45,7 +45,6 @@
 
     private AbstractPlainSocketImpl impl = null;
     private byte temp[] = new byte[1];
-    private Socket socket = null;
 
     /**
      * Creates a new SocketOutputStream. Can only be called
@@ -56,7 +55,6 @@
     SocketOutputStream(AbstractPlainSocketImpl impl) throws IOException {
         super(impl.getFileDescriptor());
         this.impl = impl;
-        socket = impl.getSocket();
     }
 
     /**
@@ -150,21 +148,10 @@
         socketWrite(b, off, len);
     }
 
-    /**
-     * Closes the stream.
-     */
-    private boolean closing = false;
     public void close() throws IOException {
-        // Prevent recursion. See BugId 4484411
-        if (closing)
-            return;
-        closing = true;
-        if (socket != null) {
-            if (!socket.isClosed())
-                socket.close();
-        } else
-            impl.close();
-        closing = false;
+        // No longer used. Socket.getOutputStream returns an
+        // OutputStream which calls Socket.close directly
+        assert false;
     }
 
     /**
--- a/src/java.base/share/classes/java/net/SocksSocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/share/classes/java/net/SocksSocketImpl.java	Thu May 02 17:29:10 2019 +0100
@@ -256,17 +256,6 @@
         connect(new InetSocketAddress(address, port), 0);
     }
 
-    @Override
-    void setSocket(Socket soc) {
-        delegate.socket = soc;
-        super.setSocket(soc);
-    }
-
-    @Override
-    void setServerSocket(ServerSocket soc) {
-        throw new InternalError("should not get here");
-    }
-
     /**
      * Connects the Socks Socket to the specified endpoint. It will first
      * connect to the SOCKS proxy and negotiate the access. If the proxy
--- a/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Thu May 02 17:29:10 2019 +0100
@@ -45,13 +45,8 @@
     /**
      * Constructs an empty instance.
      */
-    PlainSocketImpl() { }
-
-    /**
-     * Constructs an instance with the given file descriptor.
-     */
-    PlainSocketImpl(FileDescriptor fd) {
-        this.fd = fd;
+    PlainSocketImpl(boolean isServer) {
+        super(isServer);
     }
 
     static final ExtendedSocketOptions extendedOptions =
@@ -90,7 +85,7 @@
 
     protected Set<SocketOption<?>> supportedOptions() {
         HashSet<SocketOption<?>> options = new HashSet<>(super.supportedOptions());
-        if (getServerSocket() != null) {
+        if (isServer) {
             options.addAll(ExtendedSocketOptions.serverSocketOptions());
         } else {
             options.addAll(ExtendedSocketOptions.clientSocketOptions());
@@ -106,12 +101,16 @@
         try {
             socketSetOption0(opt, b, val);
         } catch (SocketException se) {
-            if (socket == null || !socket.isConnected())
+            if (!isConnected)
                 throw se;
         }
     }
 
-    native void socketCreate(boolean isServer) throws IOException;
+    void socketCreate(boolean stream) throws IOException {
+        socketCreate(stream, isServer);
+    }
+
+    native void socketCreate(boolean stream, boolean isServer) throws IOException;
 
     native void socketConnect(InetAddress address, int port, int timeout)
         throws IOException;
--- a/src/java.base/unix/native/libnet/PlainSocketImpl.c	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/unix/native/libnet/PlainSocketImpl.c	Thu May 02 17:29:10 2019 +0100
@@ -43,7 +43,6 @@
 jfieldID psi_localportID;
 jfieldID psi_timeoutID;
 jfieldID psi_trafficClassID;
-jfieldID psi_serverSocketID;
 jfieldID psi_fdLockID;
 jfieldID psi_closePendingID;
 
@@ -128,9 +127,6 @@
     CHECK_NULL(psi_timeoutID);
     psi_trafficClassID = (*env)->GetFieldID(env, cls, "trafficClass", "I");
     CHECK_NULL(psi_trafficClassID);
-    psi_serverSocketID = (*env)->GetFieldID(env, cls, "serverSocket",
-                        "Ljava/net/ServerSocket;");
-    CHECK_NULL(psi_serverSocketID);
     psi_fdLockID = (*env)->GetFieldID(env, cls, "fdLock",
                                       "Ljava/lang/Object;");
     CHECK_NULL(psi_fdLockID);
@@ -156,10 +152,10 @@
 /*
  * Class:     java_net_PlainSocketImpl
  * Method:    socketCreate
- * Signature: (Z)V */
+ * Signature: (ZZ)V */
 JNIEXPORT void JNICALL
 Java_java_net_PlainSocketImpl_socketCreate(JNIEnv *env, jobject this,
-                                           jboolean stream) {
+                                           jboolean stream, jboolean isServer) {
     jobject fdObj, ssObj;
     int fd;
     int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
@@ -204,8 +200,7 @@
      * If this is a server socket then enable SO_REUSEADDR
      * automatically and set to non blocking.
      */
-    ssObj = (*env)->GetObjectField(env, this, psi_serverSocketID);
-    if (ssObj != NULL) {
+    if (isServer) {
         int arg = 1;
         SET_NONBLOCKING(fd);
         if (NET_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
--- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Thu May 02 17:29:10 2019 +0100
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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
@@ -65,14 +65,8 @@
     /**
      * Constructs an empty instance.
      */
-    public PlainSocketImpl() {
-    }
-
-    /**
-     * Constructs an instance with the given file descriptor.
-     */
-    public PlainSocketImpl(FileDescriptor fd) {
-        this.fd = fd;
+    PlainSocketImpl(boolean isServer) {
+        super(isServer);
     }
 
     @Override
@@ -222,7 +216,7 @@
             if (preferIPv4Stack) {
                 // Don't enable the socket option on ServerSocket as it's
                 // meaningless (we don't receive on a ServerSocket).
-                if (serverSocket == null) {
+                if (!isServer) {
                     setSoTimeout0(nativefd, ((Integer)value).intValue());
                 }
             } // else timeout is implemented through select.
--- a/test/jdk/java/net/Socket/OldImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2005, 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.
- */
-
-import java.io.*;
-import java.net.*;
-
-
-/**
- * @test
- * @bug 5089488
- * @summary  java.net.Socket checks for old-style impls
- */
-
-public class OldImpl {
-
-    /**
-     * A no-op SocketImpl descendant.
-     */
-    static class FunkySocketImpl extends SocketImpl {
-        protected void accept(SocketImpl impl) throws IOException {
-        }
-
-        protected int available(){
-            return 0;
-        }
-
-        protected void bind(InetAddress host, int port){
-        }
-
-        protected void close(){
-        }
-
-        protected void connect(InetAddress address, int port){
-        }
-
-        protected void connect(String host, int port){
-        }
-
-        protected void connect(SocketAddress a,int b){
-        }
-
-        protected void create(boolean stream){
-        }
-
-        protected InputStream getInputStream(){
-            return null;
-        }
-
-        protected OutputStream getOutputStream(){
-            return null;
-        }
-
-        protected void listen(int backlog){
-        }
-
-        public Object getOption(int optID){
-            return null;
-        }
-
-        public void setOption(int optID, Object value){
-        }
-
-        protected void sendUrgentData(int i){
-        }
-    }
-
-    static class FunkyWunkySocketImpl extends FunkySocketImpl {}
-
-    /**
-     * A no-op Socket descendant.
-     */
-    static class FunkySocket extends Socket {
-        public FunkySocket(SocketImpl impl) throws IOException {
-            super(impl);
-        }
-    }
-
-    public static void main(String args[]) throws Exception {
-        FunkyWunkySocketImpl socketImpl = new FunkyWunkySocketImpl();
-        FunkySocket socko = new FunkySocket(socketImpl);
-        if (socko.isBound()) {
-            throw new RuntimeException ("socket is not really bound");
-        }
-    }
-}
--- a/test/jdk/java/net/Socket/OldSocketImpl.java	Mon Apr 29 17:54:15 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,74 +0,0 @@
-/*
- * Copyright (c) 2006, 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.
- */
-
-import java.io.*;
-import java.net.*;
-
-class OldSocketImpl extends SocketImpl  {
-    public static void main(String[] args) throws Exception {
-        Socket.setSocketImplFactory(new SocketImplFactory() {
-                public SocketImpl createSocketImpl() {
-                    return new OldSocketImpl();
-                }
-        });
-        Socket socket = new Socket("localhost", 23);
-    }
-
-    public void setOption(int optID, Object value) throws SocketException { }
-
-    public Object getOption(int optID) throws SocketException {
-        return null;
-    }
-
-    protected void create(boolean stream) throws IOException { }
-
-    protected void connect(String host, int port) throws IOException { }
-
-    protected void connect(InetAddress address, int port) throws IOException { }
-
-    // Not in 1.3...
-    // protected void connect(SocketAddress address, int timeout) throws IOException { }
-
-    protected void bind(InetAddress host, int port) throws IOException { }
-
-    protected void listen(int backlog) throws IOException { }
-
-    protected void accept(SocketImpl s) throws IOException { }
-
-    protected InputStream getInputStream() throws IOException {
-        return null;
-    }
-
-    protected OutputStream getOutputStream() throws IOException {
-        return null;
-    }
-
-    protected int available() throws IOException {
-        return 0;
-    }
-
-    protected void close() throws IOException { }
-
-    protected void sendUrgentData (int data) throws SocketException { }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/OldSocketImplTest.java	Thu May 02 17:29:10 2019 +0100
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8216978
+ * @summary Drop support for pre JDK 1.4 SocketImpl implementations
+ * @library OldSocketImpl.jar
+ * @run main/othervm OldSocketImplTest
+ */
+
+import java.net.*;
+
+public class OldSocketImplTest {
+    public static void main(String[] args) throws Exception {
+        Socket.setSocketImplFactory(new SocketImplFactory() {
+                public SocketImpl createSocketImpl() {
+                    return new OldSocketImpl();
+                }
+        });
+        try {
+            Socket socket = new Socket("localhost", 23);
+            throw new RuntimeException("error test failed");
+        } catch (AbstractMethodError error) {
+            error.printStackTrace();
+            System.out.println("Old impl no longer accepted: OK");
+        }
+    }
+}
--- a/test/jdk/java/net/Socket/OldSocketImplTestDriver.java	Mon Apr 29 17:54:15 2019 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 2017, 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.
- */
-
-import jdk.test.lib.process.ProcessTools;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-/**
- * @test
- * @bug 6449565
- * @library /test/lib
- * @build jdk.test.lib.Utils
- *        jdk.test.lib.Asserts
- *        jdk.test.lib.JDKToolFinder
- *        jdk.test.lib.JDKToolLauncher
- *        jdk.test.lib.Platform
- *        jdk.test.lib.process.*
- * @run main OldSocketImplTestDriver
- * @summary Test driver for OdlSocketImpl
- */
-public class OldSocketImplTestDriver {
-    public static void main(String[] args) throws Throwable {
-        Path jar = Paths.get(System.getProperty("test.src"),
-                "OldSocketImpl.jar");
-        ProcessTools.executeTestJava("-cp", jar.toString(), "OldSocketImpl")
-                    .outputTo(System.out)
-                    .errorTo(System.out)
-                    .shouldHaveExitValue(0);
-    }
-}