6432031: Add support for SO_REUSEPORT
authoralanb
Tue, 23 Feb 2016 17:41:00 +0000
changeset 36115 0676e37a0b9c
parent 36114 a5ed9456c9be
child 36116 b386aa77e834
6432031: Add support for SO_REUSEPORT Reviewed-by: alanb, simonis, chegar Contributed-by: yingqi.lu@intel.com
jdk/make/mapfiles/libnet/mapfile-vers
jdk/make/mapfiles/libnio/mapfile-linux
jdk/make/mapfiles/libnio/mapfile-macosx
jdk/make/mapfiles/libnio/mapfile-solaris
jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c
jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java
jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java
jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java
jdk/src/java.base/share/classes/java/net/MulticastSocket.java
jdk/src/java.base/share/classes/java/net/SocketImpl.java
jdk/src/java.base/share/classes/java/net/SocketOptions.java
jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java
jdk/src/java.base/share/classes/jdk/net/Sockets.java
jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java
jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java
jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java
jdk/src/java.base/share/classes/sun/nio/ch/Net.java
jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java
jdk/src/java.base/share/native/libnet/net_util.c
jdk/src/java.base/share/native/libnet/net_util.h
jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java
jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java
jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c
jdk/src/java.base/unix/native/libnet/SdpSupport.c
jdk/src/java.base/unix/native/libnet/SocketImpl.c
jdk/src/java.base/unix/native/libnet/net_util_md.c
jdk/src/java.base/unix/native/libnet/net_util_md.h
jdk/src/java.base/unix/native/libnio/ch/Net.c
jdk/src/java.base/unix/native/libnio/ch/nio_util.h
jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java
jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java
jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java
jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java
jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java
jdk/src/java.base/windows/native/libnet/SocketImpl.c
jdk/src/java.base/windows/native/libnet/net_util_md.c
jdk/src/java.base/windows/native/libnet/net_util_md.h
jdk/src/java.base/windows/native/libnio/ch/Net.c
jdk/test/java/net/SocketOption/OptionsTest.java
jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java
jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java
jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java
jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java
--- a/jdk/make/mapfiles/libnet/mapfile-vers	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/make/mapfiles/libnet/mapfile-vers	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1997, 2016, 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
@@ -87,6 +87,9 @@
 		Java_java_net_PlainSocketImpl_socketConnect;
 		Java_java_net_PlainDatagramSocketImpl_getTimeToLive;
 		Java_java_net_PlainDatagramSocketImpl_setTimeToLive;
+                Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0;
+                Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0;
+                Java_jdk_net_Sockets_isReusePortAvailable0;
 		Java_sun_net_PortConfig_getUpper0;
 		Java_sun_net_PortConfig_getLower0;
 		Java_sun_net_dns_ResolverConfigurationImpl_localDomain0;
@@ -112,6 +115,7 @@
 		NET_EnableFastTcpLoopback;
 		NET_ThrowNew;
                 ipv6_available;
+                reuseport_available;
                 initInetAddressIDs;
 
 	local:
--- a/jdk/make/mapfiles/libnio/mapfile-linux	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/make/mapfiles/libnio/mapfile-linux	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2016, 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
@@ -109,6 +109,7 @@
 		Java_sun_nio_ch_Net_setIntOption0;
                 Java_sun_nio_ch_Net_initIDs;
 		Java_sun_nio_ch_Net_isIPv6Available0;
+                Java_sun_nio_ch_Net_isReusePortAvailable0;
 		Java_sun_nio_ch_Net_joinOrDrop4;
 		Java_sun_nio_ch_Net_blockOrUnblock4;
 		Java_sun_nio_ch_Net_joinOrDrop6;
--- a/jdk/make/mapfiles/libnio/mapfile-macosx	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/make/mapfiles/libnio/mapfile-macosx	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2016, 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
@@ -102,6 +102,7 @@
 		Java_sun_nio_ch_Net_setIntOption0;
                 Java_sun_nio_ch_Net_initIDs;
 		Java_sun_nio_ch_Net_isIPv6Available0;
+                Java_sun_nio_ch_Net_isReusePortAvailable0;
 		Java_sun_nio_ch_Net_joinOrDrop4;
 		Java_sun_nio_ch_Net_blockOrUnblock4;
 		Java_sun_nio_ch_Net_joinOrDrop6;
--- a/jdk/make/mapfiles/libnio/mapfile-solaris	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/make/mapfiles/libnio/mapfile-solaris	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 2016, 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
@@ -97,6 +97,7 @@
 		Java_sun_nio_ch_Net_setIntOption0;
                 Java_sun_nio_ch_Net_initIDs;
 		Java_sun_nio_ch_Net_isIPv6Available0;
+                Java_sun_nio_ch_Net_isReusePortAvailable0;
 		Java_sun_nio_ch_Net_joinOrDrop4;
 		Java_sun_nio_ch_Net_blockOrUnblock4;
 		Java_sun_nio_ch_Net_joinOrDrop6;
--- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -34,6 +34,21 @@
 #include <netinet/tcp.h>
 #endif
 
+/* Defines SO_REUSEPORT */
+#if !defined(SO_REUSEPORT)
+#ifdef _WIN32
+#define SO_REUSEPORT 0
+#elif __linux__
+#define SO_REUSEPORT 15
+#elif __solaris__
+#define SO_REUSEPORT 0x100e
+#elif defined(AIX) || defined(MACOSX)
+#define SO_REUSEPORT 0x0200
+#else
+#define SO_REUSEPORT 0
+#endif
+#endif
+
 /**
  * Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level
  * socket options to the platform specific level and option.
@@ -102,6 +117,7 @@
     emit_unspec("StandardSocketOptions.SO_SNDBUF",    SOL_SOCKET, SO_SNDBUF);
     emit_unspec("StandardSocketOptions.SO_RCVBUF",    SOL_SOCKET, SO_RCVBUF);
     emit_unspec("StandardSocketOptions.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR);
+    emit_unspec("StandardSocketOptions.SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT);
     emit_unspec("StandardSocketOptions.TCP_NODELAY",  IPPROTO_TCP, TCP_NODELAY);
 
     emit_inet("StandardSocketOptions.IP_TOS",            IPPROTO_IP,     IP_TOS);
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -28,6 +28,9 @@
 import java.io.IOException;
 import java.security.AccessController;
 import sun.net.ResourceManager;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
 
 /**
  * Abstract datagram and multicast socket implementation base class.
@@ -70,6 +73,45 @@
             });
     }
 
+    private static volatile boolean checkedReusePort;
+    private static volatile boolean isReusePortAvailable;
+
+    /**
+     * Tells whether SO_REUSEPORT is supported.
+     */
+    static boolean isReusePortAvailable() {
+        if (!checkedReusePort) {
+            isReusePortAvailable = isReusePortAvailable0();
+            checkedReusePort = true;
+        }
+        return isReusePortAvailable;
+    }
+
+    private static volatile Set<SocketOption<?>> socketOptions;
+
+    /**
+     * Returns a set of SocketOptions supported by this impl
+     * and by this impl's socket (Socket or ServerSocket)
+     *
+     * @return a Set of SocketOptions
+     */
+    @Override
+    protected Set<SocketOption<?>> supportedOptions() {
+        Set<SocketOption<?>> options = socketOptions;
+        if (options == null) {
+            if (isReusePortAvailable()) {
+                options = new HashSet<>();
+                options.addAll(super.supportedOptions());
+                options.add(StandardSocketOptions.SO_REUSEPORT);
+                options = Collections.unmodifiableSet(options);
+            } else {
+                options = super.supportedOptions();
+            }
+            socketOptions = options;
+        }
+        return options;
+    }
+
     /**
      * Creates a datagram socket
      */
@@ -303,6 +345,14 @@
              if (o == null || !(o instanceof Boolean))
                  throw new SocketException("bad argument for IP_MULTICAST_LOOP");
              break;
+         case SO_REUSEPORT:
+             if (o == null || !(o instanceof Boolean)) {
+                 throw new SocketException("bad argument for SO_REUSEPORT");
+             }
+             if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+                 throw new UnsupportedOperationException("unsupported option");
+             }
+             break;
          default:
              throw new SocketException("invalid option: " + optID);
          }
@@ -343,6 +393,13 @@
                 result = socketGetOption(optID);
                 break;
 
+            case SO_REUSEPORT:
+                if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+                    throw new UnsupportedOperationException("unsupported option");
+                }
+                result = socketGetOption(optID);
+                break;
+
             default:
                 throw new SocketException("invalid option: " + optID);
         }
@@ -364,4 +421,5 @@
     }
 
     abstract int dataAvailable();
+    private static native boolean isReusePortAvailable0();
 }
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -33,6 +33,9 @@
 import sun.net.ConnectionResetException;
 import sun.net.NetHooks;
 import sun.net.ResourceManager;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Collections;
 
 /**
  * Default Socket Implementation. This implementation does
@@ -87,6 +90,45 @@
             });
     }
 
+    private static volatile boolean checkedReusePort;
+    private static volatile boolean isReusePortAvailable;
+
+    /**
+     * Tells whether SO_REUSEPORT is supported.
+     */
+    static boolean isReusePortAvailable() {
+        if (!checkedReusePort) {
+            isReusePortAvailable = isReusePortAvailable0();
+            checkedReusePort = true;
+        }
+        return isReusePortAvailable;
+    }
+
+    private static volatile Set<SocketOption<?>> socketOptions;
+
+   /**
+    * Returns a set of SocketOptions supported by this impl
+    * and by this impl's socket (Socket or ServerSocket)
+    *
+    * @return a Set of SocketOptions
+    */
+    @Override
+    protected Set<SocketOption<?>> supportedOptions() {
+        Set<SocketOption<?>> options = socketOptions;
+        if (options == null) {
+            if (isReusePortAvailable()) {
+                options = new HashSet<>();
+                options.addAll(super.supportedOptions());
+                options.add(StandardSocketOptions.SO_REUSEPORT);
+                options = Collections.unmodifiableSet(options);
+            } else {
+                options = super.supportedOptions();
+            }
+            socketOptions = options;
+        }
+        return options;
+    }
+
     /**
      * Creates a socket with a boolean that specifies whether this
      * is a stream socket (true) or an unconnected UDP socket (false).
@@ -269,6 +311,13 @@
                 throw new SocketException("bad parameter for SO_REUSEADDR");
             on = ((Boolean)val).booleanValue();
             break;
+        case SO_REUSEPORT:
+            if (val == null || !(val instanceof Boolean))
+                throw new SocketException("bad parameter for SO_REUSEPORT");
+            if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT))
+                throw new UnsupportedOperationException("unsupported option");
+            on = ((Boolean)val).booleanValue();
+            break;
         default:
             throw new SocketException("unrecognized TCP option: " + opt);
         }
@@ -326,6 +375,12 @@
         case SO_KEEPALIVE:
             ret = socketGetOption(opt, null);
             return Boolean.valueOf(ret != -1);
+        case SO_REUSEPORT:
+            if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+                throw new UnsupportedOperationException("unsupported option");
+            }
+            ret = socketGetOption(opt, null);
+            return Boolean.valueOf(ret != -1);
         // should never get here
         default:
             return null;
@@ -723,4 +778,6 @@
 
     public static final int SHUT_RD = 0;
     public static final int SHUT_WR = 1;
+
+    private static native boolean isReusePortAvailable0();
 }
--- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -287,6 +287,9 @@
             setOption(SocketOptions.SO_RCVBUF, value);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             setOption(SocketOptions.SO_REUSEADDR, value);
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            setOption(SocketOptions.SO_REUSEPORT, value);
         } else if (name == StandardSocketOptions.IP_TOS) {
             setOption(SocketOptions.IP_TOS, value);
         } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
@@ -329,6 +332,9 @@
             return (T) getOption(SocketOptions.SO_RCVBUF);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             return (T) getOption(SocketOptions.SO_REUSEADDR);
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            return (T) getOption(SocketOptions.SO_REUSEPORT);
         } else if (name == StandardSocketOptions.IP_TOS) {
             return (T) getOption(SocketOptions.IP_TOS);
         } else if (name == StandardSocketOptions.IP_MULTICAST_IF &&
--- a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -98,7 +98,11 @@
      * <p>
      * When the socket is created the
      * {@link DatagramSocket#setReuseAddress(boolean)} method is
-     * called to enable the SO_REUSEADDR socket option.
+     * called to enable the SO_REUSEADDR socket option. When
+     * {@link StandardSocketOptions#SO_REUSEPORT SO_REUSEPORT} is
+     * supported then
+     * {@link DatagramSocketImpl#setOption(SocketOption, Object)}
+     * is called to enable the socket option.
      *
      * @exception IOException if an I/O exception occurs
      * while creating the MulticastSocket
@@ -106,6 +110,7 @@
      *             {@code checkListen} method doesn't allow the operation.
      * @see SecurityManager#checkListen
      * @see java.net.DatagramSocket#setReuseAddress(boolean)
+     * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object)
      */
     public MulticastSocket() throws IOException {
         this(new InetSocketAddress(0));
@@ -167,6 +172,11 @@
         // Enable SO_REUSEADDR before binding
         setReuseAddress(true);
 
+        // Enable SO_REUSEPORT if supported before binding
+        if (supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+            this.setOption(StandardSocketOptions.SO_REUSEPORT, true);
+        }
+
         if (bindaddr != null) {
             try {
                 bind(bindaddr);
--- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1995, 2016, 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
@@ -386,6 +386,9 @@
             setOption(SocketOptions.SO_RCVBUF, value);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             setOption(SocketOptions.SO_REUSEADDR, value);
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            setOption(SocketOptions.SO_REUSEPORT, value);
         } else if (name == StandardSocketOptions.SO_LINGER &&
                 (getSocket() != null)) {
             setOption(SocketOptions.SO_LINGER, value);
@@ -426,6 +429,9 @@
             return (T)getOption(SocketOptions.SO_RCVBUF);
         } else if (name == StandardSocketOptions.SO_REUSEADDR) {
             return (T)getOption(SocketOptions.SO_REUSEADDR);
+        } else if (name == StandardSocketOptions.SO_REUSEPORT &&
+            supportedOptions().contains(name)) {
+            return (T)getOption(SocketOptions.SO_REUSEPORT);
         } else if (name == StandardSocketOptions.SO_LINGER &&
                 (getSocket() != null)) {
             return (T)getOption(SocketOptions.SO_LINGER);
--- a/jdk/src/java.base/share/classes/java/net/SocketOptions.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2016, 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
@@ -170,6 +170,17 @@
 
     @Native public static final int SO_REUSEADDR = 0x04;
 
+    /** Sets SO_REUSEPORT for a socket. This option enables and disables
+     *  the ability to have multiple sockets listen to the same address
+     *  and port.
+     * <P>
+     * Valid for: SocketImpl, DatagramSocketImpl
+     *
+     * @since 9
+     * @see StandardSocketOptions#SO_REUSEPORT
+     */
+    @Native public static final int SO_REUSEPORT = 0x0E;
+
     /**
      * Sets SO_BROADCAST for a socket. This option enables and disables
      * the ability of the process to send broadcast messages. It is supported
--- a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -187,6 +187,29 @@
         new StdSocketOption<Boolean>("SO_REUSEADDR", Boolean.class);
 
     /**
+     * Re-use port.
+     *
+     * <p> The value of this socket option is a {@code Boolean} that represents
+     * whether the option is enabled or disabled. The exact semantics of this
+     * socket option are socket type and system dependent.
+     *
+     * <p> In the case of stream-oriented sockets, this socket option usually allows
+     * multiple listening sockets to be bound to both same address
+     * and same port.
+     *
+     * <p> For datagram-oriented sockets the socket option usually allows
+     * multiple UDP sockets to be bound to the same address and port.
+     *
+     * <p> An implementation allows this socket option to be set before the
+     * socket is bound or connected. Changing the value of this socket option
+     * after the socket is bound has no effect.
+     *
+     * @since 9
+     */
+    public static final SocketOption<Boolean> SO_REUSEPORT =
+        new StdSocketOption<Boolean>("SO_REUSEPORT", Boolean.class);
+
+    /**
      * Linger on close if data is present.
      *
      * <p> The value of this socket option is an {@code Integer} that controls
--- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/jdk/net/Sockets.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 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
@@ -251,9 +251,23 @@
         }
     }
 
+    private static volatile boolean checkedReusePort;
+    private static volatile boolean isReusePortAvailable;
+
+    /**
+     * Tells whether SO_REUSEPORT is supported.
+     */
+    static boolean isReusePortAvailable() {
+        if (!checkedReusePort) {
+            isReusePortAvailable = isReusePortAvailable0();
+            checkedReusePort = true;
+        }
+        return isReusePortAvailable;
+    }
+
     private static void initOptionSets() {
         boolean flowsupported = ExtendedOptionsImpl.flowSupported();
-
+        boolean reuseportsupported = isReusePortAvailable();
         // Socket
 
         Set<SocketOption<?>> set = new HashSet<>();
@@ -261,6 +275,9 @@
         set.add(StandardSocketOptions.SO_SNDBUF);
         set.add(StandardSocketOptions.SO_RCVBUF);
         set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
         set.add(StandardSocketOptions.SO_LINGER);
         set.add(StandardSocketOptions.IP_TOS);
         set.add(StandardSocketOptions.TCP_NODELAY);
@@ -275,6 +292,9 @@
         set = new HashSet<>();
         set.add(StandardSocketOptions.SO_RCVBUF);
         set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
         set.add(StandardSocketOptions.IP_TOS);
         set = Collections.unmodifiableSet(set);
         options.put(ServerSocket.class, set);
@@ -285,6 +305,9 @@
         set.add(StandardSocketOptions.SO_SNDBUF);
         set.add(StandardSocketOptions.SO_RCVBUF);
         set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
         set.add(StandardSocketOptions.IP_TOS);
         if (flowsupported) {
             set.add(ExtendedSocketOptions.SO_FLOW_SLA);
@@ -298,6 +321,9 @@
         set.add(StandardSocketOptions.SO_SNDBUF);
         set.add(StandardSocketOptions.SO_RCVBUF);
         set.add(StandardSocketOptions.SO_REUSEADDR);
+        if (reuseportsupported) {
+            set.add(StandardSocketOptions.SO_REUSEPORT);
+        }
         set.add(StandardSocketOptions.IP_TOS);
         set.add(StandardSocketOptions.IP_MULTICAST_IF);
         set.add(StandardSocketOptions.IP_MULTICAST_TTL);
@@ -308,4 +334,6 @@
         set = Collections.unmodifiableSet(set);
         options.put(MulticastSocket.class, set);
     }
+
+    private static native boolean isReusePortAvailable0();
 }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -231,6 +231,9 @@
             HashSet<SocketOption<?>> set = new HashSet<>(2);
             set.add(StandardSocketOptions.SO_RCVBUF);
             set.add(StandardSocketOptions.SO_REUSEADDR);
+            if (Net.isReusePortAvailable()) {
+                set.add(StandardSocketOptions.SO_REUSEPORT);
+            }
             return Collections.unmodifiableSet(set);
         }
     }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -508,6 +508,9 @@
             set.add(StandardSocketOptions.SO_RCVBUF);
             set.add(StandardSocketOptions.SO_KEEPALIVE);
             set.add(StandardSocketOptions.SO_REUSEADDR);
+            if (Net.isReusePortAvailable()) {
+                set.add(StandardSocketOptions.SO_REUSEPORT);
+            }
             set.add(StandardSocketOptions.TCP_NODELAY);
             if (ExtendedOptionsImpl.flowSupported()) {
                 set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA);
--- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -298,6 +298,9 @@
             set.add(StandardSocketOptions.SO_SNDBUF);
             set.add(StandardSocketOptions.SO_RCVBUF);
             set.add(StandardSocketOptions.SO_REUSEADDR);
+            if (Net.isReusePortAvailable()) {
+                set.add(StandardSocketOptions.SO_REUSEPORT);
+            }
             set.add(StandardSocketOptions.SO_BROADCAST);
             set.add(StandardSocketOptions.IP_TOS);
             set.add(StandardSocketOptions.IP_MULTICAST_IF);
--- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -56,6 +56,8 @@
 
     private static volatile boolean checkedIPv6;
     private static volatile boolean isIPv6Available;
+    private static volatile boolean checkedReusePort;
+    private static volatile boolean isReusePortAvailable;
 
     /**
      * Tells whether dual-IPv4/IPv6 sockets should be used.
@@ -69,6 +71,17 @@
     }
 
     /**
+     * Tells whether SO_REUSEPORT is supported.
+     */
+    static boolean isReusePortAvailable() {
+        if (!checkedReusePort) {
+            isReusePortAvailable = isReusePortAvailable0();
+            checkedReusePort = true;
+        }
+        return isReusePortAvailable;
+    }
+
+    /**
      * Returns true if exclusive binding is on
      */
     static boolean useExclusiveBind() {
@@ -389,6 +402,8 @@
 
     private static native boolean isIPv6Available0();
 
+    private static native boolean isReusePortAvailable0();
+
     /*
      * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS
      */
--- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -33,7 +33,6 @@
 import java.util.*;
 import sun.net.NetHooks;
 
-
 /**
  * An implementation of ServerSocketChannels
  */
@@ -185,6 +184,9 @@
             HashSet<SocketOption<?>> set = new HashSet<>(2);
             set.add(StandardSocketOptions.SO_RCVBUF);
             set.add(StandardSocketOptions.SO_REUSEADDR);
+            if (Net.isReusePortAvailable()) {
+                set.add(StandardSocketOptions.SO_REUSEPORT);
+            }
             set.add(StandardSocketOptions.IP_TOS);
             return Collections.unmodifiableSet(set);
         }
--- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -234,6 +234,9 @@
             set.add(StandardSocketOptions.SO_RCVBUF);
             set.add(StandardSocketOptions.SO_KEEPALIVE);
             set.add(StandardSocketOptions.SO_REUSEADDR);
+            if (Net.isReusePortAvailable()) {
+                set.add(StandardSocketOptions.SO_REUSEPORT);
+            }
             set.add(StandardSocketOptions.SO_LINGER);
             set.add(StandardSocketOptions.TCP_NODELAY);
             // additional options required by socket adaptor
--- a/jdk/src/java.base/share/native/libnet/net_util.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, 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
@@ -29,14 +29,21 @@
 #include "net_util.h"
 
 int IPv6_supported() ;
+int reuseport_supported() ;
 
 static int IPv6_available;
+static int REUSEPORT_available;
 
 JNIEXPORT jint JNICALL ipv6_available()
 {
     return IPv6_available ;
 }
 
+JNIEXPORT jint JNICALL reuseport_available()
+{
+    return REUSEPORT_available;
+}
+
 JNIEXPORT jint JNICALL
 DEF_JNI_OnLoad(JavaVM *vm, void *reserved)
 {
@@ -45,7 +52,6 @@
     jmethodID mid;
     jstring s;
     jint preferIPv4Stack;
-
     if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) {
         return JNI_EVERSION; /* JNI version not supported */
     }
@@ -64,6 +70,9 @@
        supporting socket APIs are available
     */
     IPv6_available = IPv6_supported() & (!preferIPv4Stack);
+
+    /* check if SO_REUSEPORT is supported on this platform */
+    REUSEPORT_available = reuseport_supported();
     platformInit();
     parseExclusiveBindProperty(env);
 
--- a/jdk/src/java.base/share/native/libnet/net_util.h	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/share/native/libnet/net_util.h	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -131,6 +131,8 @@
 
 JNIEXPORT jint JNICALL ipv6_available() ;
 
+JNIEXPORT jint JNICALL reuseport_available() ;
+
 void
 NET_AllocSockaddr(struct sockaddr **him, int *len);
 
--- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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,15 @@
 
     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
         if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
-            super.setOption(name, value);
+            if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
+                super.setOption(name, value);
+            } else {
+               if (supportedOptions().contains(name)) {
+                   super.setOption(name, value);
+               } else {
+                   throw new UnsupportedOperationException("unsupported option");
+               }
+            }
         } else {
             if (!flowSupported()) {
                 throw new UnsupportedOperationException("unsupported option");
@@ -62,7 +70,15 @@
     @SuppressWarnings("unchecked")
     protected <T> T getOption(SocketOption<T> name) throws IOException {
         if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
-            return super.getOption(name);
+            if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
+                return super.getOption(name);
+            } else {
+                if (supportedOptions().contains(name)) {
+                    return super.getOption(name);
+                } else {
+                    throw new UnsupportedOperationException("unsupported option");
+                }
+            }
         }
         if (!flowSupported()) {
             throw new UnsupportedOperationException("unsupported option");
@@ -87,6 +103,9 @@
     }
 
     protected void socketSetOption(int opt, Object val) throws SocketException {
+        if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
         try {
             socketSetOption0(opt, val);
         } catch (SocketException se) {
--- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -59,7 +59,15 @@
 
     protected <T> void setOption(SocketOption<T> name, T value) throws IOException {
         if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
-            super.setOption(name, value);
+            if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
+                super.setOption(name, value);
+            } else {
+                if (supportedOptions().contains(name)) {
+                    super.setOption(name, value);
+                } else {
+                    throw new UnsupportedOperationException("unsupported option");
+                }
+            }
         } else {
             if (getSocket() == null || !flowSupported()) {
                 throw new UnsupportedOperationException("unsupported option");
@@ -76,7 +84,15 @@
     @SuppressWarnings("unchecked")
     protected <T> T getOption(SocketOption<T> name) throws IOException {
         if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) {
-            return super.getOption(name);
+            if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) {
+                return super.getOption(name);
+            } else {
+                if (supportedOptions().contains(name)) {
+                    return super.getOption(name);
+                } else {
+                    throw new UnsupportedOperationException("unsupported option");
+                }
+            }
         }
         if (getSocket() == null || !flowSupported()) {
             throw new UnsupportedOperationException("unsupported option");
@@ -101,6 +117,9 @@
     }
 
     protected void socketSetOption(int opt, boolean b, Object val) throws SocketException {
+        if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
         try {
             socketSetOption0(opt, b, val);
         } catch (SocketException se) {
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -1392,6 +1392,7 @@
             }
 
         case java_net_SocketOptions_SO_REUSEADDR:
+        case java_net_SocketOptions_SO_REUSEPORT:
         case java_net_SocketOptions_SO_BROADCAST:
             {
                 jclass cls;
@@ -1769,6 +1770,9 @@
         case java_net_SocketOptions_SO_REUSEADDR:
             return createBoolean(env, optval.i);
 
+        case java_net_SocketOptions_SO_REUSEPORT:
+            return createBoolean(env, optval.i);
+
         case java_net_SocketOptions_SO_SNDBUF:
         case java_net_SocketOptions_SO_RCVBUF:
         case java_net_SocketOptions_IP_TOS:
--- a/jdk/src/java.base/unix/native/libnet/SdpSupport.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/SdpSupport.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2016, 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
@@ -108,6 +108,11 @@
         len = sizeof(arg);
         if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0)
             setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len);
+#ifdef SO_REUSEPORT
+        len = sizeof(arg);
+        if (getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, &len) == 0)
+            setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, len);
+#endif
         len = sizeof(arg);
         if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0)
             setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/unix/native/libnet/SocketImpl.c	Tue Feb 23 17:41:00 2016 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include <jni.h>
+#include <string.h>
+
+#include "net_util.h"
+
+JNIEXPORT jboolean JNICALL
+Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
+}
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -439,6 +439,25 @@
 }
 #endif /* DONT_ENABLE_IPV6 */
 
+jint reuseport_supported()
+{
+    /* Do a simple dummy call, and try to figure out from that */
+    int one = 1;
+    int rv, s;
+    s = socket(PF_INET, SOCK_STREAM, 0);
+    if (s < 0) {
+        return JNI_FALSE;
+    }
+    rv = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void *)&one, sizeof(one));
+    if (rv != 0) {
+        rv = JNI_FALSE;
+    } else {
+        rv = JNI_TRUE;
+    }
+    close(s);
+    return rv;
+}
+
 void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env,
                                                const char* hostname,
                                                int gai_error)
@@ -1014,6 +1033,7 @@
         { java_net_SocketOptions_SO_RCVBUF,             SOL_SOCKET,     SO_RCVBUF },
         { java_net_SocketOptions_SO_KEEPALIVE,          SOL_SOCKET,     SO_KEEPALIVE },
         { java_net_SocketOptions_SO_REUSEADDR,          SOL_SOCKET,     SO_REUSEADDR },
+        { java_net_SocketOptions_SO_REUSEPORT,          SOL_SOCKET,     SO_REUSEPORT },
         { java_net_SocketOptions_SO_BROADCAST,          SOL_SOCKET,     SO_BROADCAST },
         { java_net_SocketOptions_IP_TOS,                IPPROTO_IP,     IP_TOS },
         { java_net_SocketOptions_IP_MULTICAST_IF,       IPPROTO_IP,     IP_MULTICAST_IF },
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -60,6 +60,19 @@
 #define NET_WAIT_WRITE   0x02
 #define NET_WAIT_CONNECT 0x04
 
+/* Defines SO_REUSEPORT */
+#ifndef SO_REUSEPORT
+#ifdef __linux__
+#define SO_REUSEPORT 15
+#elif __solaris__
+#define SO_REUSEPORT 0x100e
+#elif defined(AIX) || defined(MACOSX)
+#define SO_REUSEPORT 0x0200
+#else
+#define SO_REUSEPORT 0
+#endif
+#endif
+
 jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout);
 
 /************************************************************************
--- a/jdk/src/java.base/unix/native/libnio/ch/Net.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -161,6 +161,12 @@
     return (ipv6_available()) ? JNI_TRUE : JNI_FALSE;
 }
 
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    return (reuseport_available()) ? JNI_TRUE : JNI_FALSE;
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
     return -1;
--- a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -36,6 +36,18 @@
   } while((_result == -1) && (errno == EINTR)); \
 } while(0)
 
+/* Defines SO_REUSEPORT */
+#ifndef SO_REUSEPORT
+#ifdef __linux__
+#define SO_REUSEPORT 15
+#elif __solaris__
+#define SO_REUSEPORT 0x100e
+#elif defined(AIX) || defined(MACOSX)
+#define SO_REUSEPORT 0x0200
+#else
+#define SO_REUSEPORT 0
+#endif
+#endif
 
 /* NIO utility procedures */
 
--- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -167,6 +167,11 @@
 
         int optionValue = 0;
 
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+
         switch(opt) {
             case IP_TOS :
             case SO_RCVBUF :
@@ -200,6 +205,9 @@
         }
         if (opt == SO_REUSEADDR && reuseAddressEmulated)
             return isReuseAddress;
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT)
+            throw new UnsupportedOperationException("unsupported option");
 
         int value = socketGetIntOption(nativefd, opt);
         Object returnValue = null;
--- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -181,6 +181,10 @@
         if (opt == SO_TIMEOUT) {  // timeout implemented through select.
             return;
         }
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
 
         int optionValue = 0;
 
@@ -224,6 +228,10 @@
             localAddress(nativefd, (InetAddressContainer)iaContainerObj);
             return 0;  // return value doesn't matter.
         }
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
 
         // SO_REUSEADDR emulated when using exclusive bind
         if (opt == SO_REUSEADDR && exclusiveBind)
--- a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -173,10 +173,18 @@
     }
 
     public void setOption(int opt, Object val) throws SocketException {
+        if (opt == SocketOptions.SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
+        }
         impl.setOption(opt, val);
     }
 
     public Object getOption(int opt) throws SocketException {
+        if (opt == SocketOptions.SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
+        }
         return impl.getOption(opt);
     }
 
@@ -332,14 +340,27 @@
 
     void socketSetOption(int cmd, boolean on, Object value)
         throws SocketException {
+        if (cmd == SocketOptions.SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
+        }
         impl.socketSetOption(cmd, on, value);
     }
 
     int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
+        if (opt == SocketOptions.SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
+        }
         return impl.socketGetOption(opt, iaContainerObj);
     }
 
     void socketSendUrgentData(int data) throws IOException {
         impl.socketSendUrgentData(data);
     }
+
+    static boolean isReusePortAvailable() {
+        // SO_REUSEPORT is not supported on Windows.
+        return false;
+    }
 }
--- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -130,6 +130,9 @@
             return socketLocalAddress(family);
         } else if (optID == SO_REUSEADDR && reuseAddressEmulated) {
             return isReuseAddress;
+        } else if (optID == SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
         } else {
             return super.getOption(optID);
         }
@@ -142,6 +145,9 @@
             // socket already bound, emulate
             reuseAddressEmulated = true;
             isReuseAddress = (Boolean)val;
+        } else if (opt == SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
         } else {
             socketNativeSetOption(opt, val);
         }
--- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -128,6 +128,9 @@
         } else if (opt == SO_REUSEADDR && exclusiveBind) {
             // SO_REUSEADDR emulated when using exclusive bind
             return isReuseAddress;
+        } else if (opt == SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
         } else
             return super.getOption(opt);
     }
@@ -144,6 +147,10 @@
         // SO_REUSEADDR emulated when using exclusive bind
         if (opt == SO_REUSEADDR && exclusiveBind)
             isReuseAddress = on;
+        else if (opt == SO_REUSEPORT) {
+            // SO_REUSEPORT is not supported on Windows.
+            throw new UnsupportedOperationException("unsupported option");
+        }
         else
             socketNativeSetOption(opt, on, value);
     }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/windows/native/libnet/SocketImpl.c	Tue Feb 23 17:41:00 2016 +0000
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, 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.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+#include <jni.h>
+
+JNIEXPORT jboolean JNICALL
+Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    // SO_REUSEPORT is not supported on Windows
+    return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    // SO_REUSEPORT is not supported on Windows
+    return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    // SO_REUSEPORT is not supported on Windows
+    return JNI_FALSE;
+}
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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
@@ -242,6 +242,11 @@
     return JNI_TRUE;
 }
 
+jint reuseport_supported()
+{
+    /* SO_REUSEPORT is not supported onn Windows */
+    return JNI_FALSE;
+}
 /*
  * Return the default TOS value
  */
--- a/jdk/src/java.base/windows/native/libnet/net_util_md.h	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h	Tue Feb 23 17:41:00 2016 +0000
@@ -54,6 +54,9 @@
 
 #else
 
+/*SO_REUSEPORT is not supported on Windows, define it to 0*/
+#define SO_REUSEPORT 0
+
 /* Retain this code a little longer to support building in
  * old environments.  _MSC_VER is defined as:
  *     1200 for MSVC++ 6.0
@@ -353,3 +356,4 @@
 
 JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP
 (JNIEnv *env, jclass cls, jstring name, jint index);
+
--- a/jdk/src/java.base/windows/native/libnio/ch/Net.c	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -93,6 +93,13 @@
     return ipv6_available() ? JNI_TRUE : JNI_FALSE;
 }
 
+JNIEXPORT jboolean JNICALL
+Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1)
+{
+    // SO_REUSEPORT is not supported on Windows
+    return JNI_FALSE;
+}
+
 JNIEXPORT jint JNICALL
 Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) {
     return 1;
--- a/jdk/test/java/net/SocketOption/OptionsTest.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/test/java/net/SocketOption/OptionsTest.java	Tue Feb 23 17:41:00 2016 +0000
@@ -54,6 +54,7 @@
         Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
         Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
         Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+        Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
         Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)),
         Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
     };
@@ -61,6 +62,7 @@
     static Test[] serverSocketTests = new Test[] {
         Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
         Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+        Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
         Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
     };
 
@@ -68,6 +70,7 @@
         Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)),
         Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)),
         Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE),
+        Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE),
         Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100))
     };
 
@@ -97,15 +100,19 @@
             Socket c = new Socket("127.0.0.1", srv.getLocalPort());
             Socket s = srv.accept();
         ) {
+            Set<SocketOption<?>> options = c.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
             for (int i=0; i<socketTests.length; i++) {
                 Test test = socketTests[i];
-                c.setOption((SocketOption)test.option, test.testValue);
-                Object getval = c.getOption((SocketOption)test.option);
-                Object legacyget = legacyGetOption(Socket.class, c,test.option);
-                if (!getval.equals(legacyget)) {
-                    Formatter f = new Formatter();
-                    f.format("S Err %d: %s/%s", i, getval, legacyget);
-                    throw new RuntimeException(f.toString());
+                if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
+                    c.setOption((SocketOption)test.option, test.testValue);
+                    Object getval = c.getOption((SocketOption)test.option);
+                    Object legacyget = legacyGetOption(Socket.class, c,test.option);
+                    if (!getval.equals(legacyget)) {
+                        Formatter f = new Formatter();
+                        f.format("S Err %d: %s/%s", i, getval, legacyget);
+                        throw new RuntimeException(f.toString());
+                    }
                 }
             }
         }
@@ -115,15 +122,19 @@
         try (
             DatagramSocket c = new DatagramSocket(0);
         ) {
+            Set<SocketOption<?>> options = c.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
             for (int i=0; i<dgSocketTests.length; i++) {
                 Test test = dgSocketTests[i];
-                c.setOption((SocketOption)test.option, test.testValue);
-                Object getval = c.getOption((SocketOption)test.option);
-                Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option);
-                if (!getval.equals(legacyget)) {
-                    Formatter f = new Formatter();
-                    f.format("DG Err %d: %s/%s", i, getval, legacyget);
-                    throw new RuntimeException(f.toString());
+                if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
+                    c.setOption((SocketOption)test.option, test.testValue);
+                    Object getval = c.getOption((SocketOption)test.option);
+                    Object legacyget = legacyGetOption(DatagramSocket.class, c,test.option);
+                    if (!getval.equals(legacyget)) {
+                        Formatter f = new Formatter();
+                        f.format("DG Err %d: %s/%s", i, getval, legacyget);
+                        throw new RuntimeException(f.toString());
+                    }
                 }
             }
         }
@@ -151,17 +162,21 @@
         try (
             ServerSocket c = new ServerSocket(0);
         ) {
+            Set<SocketOption<?>> options = c.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
             for (int i=0; i<serverSocketTests.length; i++) {
                 Test test = serverSocketTests[i];
-                c.setOption((SocketOption)test.option, test.testValue);
-                Object getval = c.getOption((SocketOption)test.option);
-                Object legacyget = legacyGetOption(
-                    ServerSocket.class, c, test.option
-                );
-                if (!getval.equals(legacyget)) {
-                    Formatter f = new Formatter();
-                    f.format("SS Err %d: %s/%s", i, getval, legacyget);
-                    throw new RuntimeException(f.toString());
+                if (!(test.option == StandardSocketOptions.SO_REUSEPORT && !reuseport)) {
+                    c.setOption((SocketOption)test.option, test.testValue);
+                    Object getval = c.getOption((SocketOption)test.option);
+                    Object legacyget = legacyGetOption(
+                        ServerSocket.class, c, test.option
+                    );
+                    if (!getval.equals(legacyget)) {
+                        Formatter f = new Formatter();
+                        f.format("SS Err %d: %s/%s", i, getval, legacyget);
+                        throw new RuntimeException(f.toString());
+                    }
                 }
             }
         }
@@ -174,6 +189,8 @@
     {
         if (type.equals(Socket.class)) {
             Socket socket = (Socket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
 
             if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) {
                 return Boolean.valueOf(socket.getKeepAlive());
@@ -183,6 +200,8 @@
                 return Integer.valueOf(socket.getReceiveBufferSize());
             } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
                 return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
             } else if (option.equals(StandardSocketOptions.SO_LINGER)) {
                 return Integer.valueOf(socket.getSoLinger());
             } else if (option.equals(StandardSocketOptions.IP_TOS)) {
@@ -194,10 +213,15 @@
             }
         } else if  (type.equals(ServerSocket.class)) {
             ServerSocket socket = (ServerSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
+
             if (option.equals(StandardSocketOptions.SO_RCVBUF)) {
                 return Integer.valueOf(socket.getReceiveBufferSize());
             } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
                 return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
             } else if (option.equals(StandardSocketOptions.IP_TOS)) {
                 return Integer.valueOf(jdk.net.Sockets.getOption(
                     socket, StandardSocketOptions.IP_TOS));
@@ -206,6 +230,8 @@
             }
         } else if  (type.equals(DatagramSocket.class)) {
             DatagramSocket socket = (DatagramSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
 
             if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
                 return Integer.valueOf(socket.getSendBufferSize());
@@ -213,6 +239,8 @@
                 return Integer.valueOf(socket.getReceiveBufferSize());
             } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
                 return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
             } else if (option.equals(StandardSocketOptions.IP_TOS)) {
                 return Integer.valueOf(socket.getTrafficClass());
             } else {
@@ -221,6 +249,8 @@
 
         } else if  (type.equals(MulticastSocket.class)) {
             MulticastSocket socket = (MulticastSocket)s;
+            Set<SocketOption<?>> options = socket.supportedOptions();
+            boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT);
 
             if (option.equals(StandardSocketOptions.SO_SNDBUF)) {
                 return Integer.valueOf(socket.getSendBufferSize());
@@ -228,6 +258,8 @@
                 return Integer.valueOf(socket.getReceiveBufferSize());
             } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) {
                 return Boolean.valueOf(socket.getReuseAddress());
+            } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) {
+                return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT));
             } else if (option.equals(StandardSocketOptions.IP_TOS)) {
                 return Integer.valueOf(socket.getTrafficClass());
             } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) {
--- a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -141,8 +141,11 @@
         try {
             // check supported options
             Set<SocketOption<?>> options = ch.supportedOptions();
+            boolean reuseport = options.contains(SO_REUSEPORT);
             if (!options.contains(SO_REUSEADDR))
                 throw new RuntimeException("SO_REUSEADDR should be supported");
+            if (!options.contains(SO_REUSEPORT) && reuseport)
+                throw new RuntimeException("SO_REUSEPORT should be supported");
             if (!options.contains(SO_RCVBUF))
                 throw new RuntimeException("SO_RCVBUF should be supported");
 
@@ -156,6 +159,13 @@
             checkOption(ch, SO_REUSEADDR, true);
             ch.setOption(SO_REUSEADDR, false);
             checkOption(ch, SO_REUSEADDR, false);
+
+            if (reuseport) {
+                ch.setOption(SO_REUSEPORT, true);
+                checkOption(ch, SO_REUSEPORT, true);
+                ch.setOption(SO_REUSEPORT, false);
+                checkOption(ch, SO_REUSEPORT, false);
+            }
         } finally {
             ch.close();
         }
--- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2016, 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
@@ -37,6 +37,7 @@
 import java.util.concurrent.atomic.*;
 import java.io.Closeable;
 import java.io.IOException;
+import java.util.Set;
 
 public class Basic {
     static final Random rand = new Random();
@@ -165,6 +166,15 @@
             // read others (can't check as actual value is implementation dependent)
             ch.getOption(SO_RCVBUF);
             ch.getOption(SO_SNDBUF);
+
+            Set<SocketOption<?>> options = ch.supportedOptions();
+            boolean reuseport = options.contains(SO_REUSEPORT);
+            if (reuseport) {
+                if (ch.getOption(SO_REUSEPORT))
+                    throw new RuntimeException("Default of SO_REUSEPORT should be 'false'");
+                if (!ch.setOption(SO_REUSEPORT, true).getOption(SO_REUSEPORT))
+                    throw new RuntimeException("SO_REUSEPORT did not change");
+            }
         }
     }
 
--- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -50,9 +50,17 @@
 
         // check supported options
         Set<SocketOption<?>> options = dc.supportedOptions();
-        List<? extends SocketOption<?>> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
-            SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL,
-            IP_MULTICAST_LOOP);
+        boolean reuseport = options.contains(SO_REUSEPORT);
+        List<? extends SocketOption<?>> expected;
+        if (reuseport) {
+           expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
+                      SO_REUSEADDR, SO_REUSEPORT, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF,
+                      IP_MULTICAST_TTL, IP_MULTICAST_LOOP);
+        } else {
+           expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF,
+                      SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL,
+                      IP_MULTICAST_LOOP);
+        }
         for (SocketOption opt: expected) {
             if (!options.contains(opt))
                 throw new RuntimeException(opt.name() + " should be supported");
@@ -83,7 +91,12 @@
         checkOption(dc, SO_REUSEADDR, true);
         dc.setOption(SO_REUSEADDR, false);
         checkOption(dc, SO_REUSEADDR, false);
-
+        if (reuseport) {
+            dc.setOption(SO_REUSEPORT, true);
+            checkOption(dc, SO_REUSEPORT, true);
+            dc.setOption(SO_REUSEPORT, false);
+            checkOption(dc, SO_REUSEPORT, false);
+        }
         // bind socket
         dc.bind(new InetSocketAddress(0));
 
--- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Tue Feb 23 09:49:04 2016 +0100
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Tue Feb 23 17:41:00 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, 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
@@ -49,8 +49,11 @@
 
         // check supported options
         Set<SocketOption<?>> options = ssc.supportedOptions();
+        boolean reuseport = options.contains(SO_REUSEPORT);
         if (!options.contains(SO_REUSEADDR))
             throw new RuntimeException("SO_REUSEADDR should be supported");
+        if (!options.contains(SO_REUSEPORT) && reuseport)
+            throw new RuntimeException("SO_REUSEPORT should be supported");
         if (!options.contains(SO_RCVBUF))
             throw new RuntimeException("SO_RCVBUF should be supported");
 
@@ -64,6 +67,12 @@
         checkOption(ssc, SO_REUSEADDR, true);
         ssc.setOption(SO_REUSEADDR, false);
         checkOption(ssc, SO_REUSEADDR, false);
+        if (reuseport) {
+            ssc.setOption(SO_REUSEPORT, true);
+            checkOption(ssc, SO_REUSEPORT, true);
+            ssc.setOption(SO_REUSEPORT, false);
+            checkOption(ssc, SO_REUSEPORT, false);
+        }
 
         // NullPointerException
         try {