diff -r a5ed9456c9be -r 0676e37a0b9c jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java --- 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> 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> supportedOptions() { + Set> 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(); }