--- a/jdk/make/lib/CoreLibraries.gmk Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/lib/CoreLibraries.gmk Wed Feb 24 08:58:31 2016 -0800
@@ -137,12 +137,6 @@
endif
endif
-ifeq ($(OPENJDK_TARGET_OS), linux)
- ifeq ($(OPENJDK_TARGET_CPU), x86_64)
- BUILD_LIBJAVA_Bits.c_CFLAGS := $(C_O_FLAG_NORM)
- endif
-endif
-
$(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
LIBRARY := java, \
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
@@ -225,7 +219,7 @@
$(call SET_SHARED_LIBRARY_ORIGIN), \
LDFLAGS_windows := -export:ZIP_Open -export:ZIP_Close -export:ZIP_FindEntry \
-export:ZIP_ReadEntry -export:ZIP_GetNextEntry \
- -export:ZIP_InflateFully, \
+ -export:ZIP_InflateFully -export:ZIP_CRC32, \
LIBS_unix := -ljvm -ljava $(LIBZ), \
LIBS_solaris := -lc, \
LIBS_windows := jvm.lib $(WIN_JAVA_LIB), \
--- a/jdk/make/mapfiles/libjava/mapfile-vers Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/mapfiles/libjava/mapfile-vers Wed Feb 24 08:58:31 2016 -0800
@@ -229,12 +229,6 @@
Java_java_lang_Throwable_fillInStackTrace;
Java_java_lang_Throwable_getStackTraceDepth;
Java_java_lang_Throwable_getStackTraceElement;
- Java_java_nio_Bits_copyFromShortArray;
- Java_java_nio_Bits_copyToShortArray;
- Java_java_nio_Bits_copyFromIntArray;
- Java_java_nio_Bits_copyToIntArray;
- Java_java_nio_Bits_copyFromLongArray;
- Java_java_nio_Bits_copyToLongArray;
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2;
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2;
Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2;
--- a/jdk/make/mapfiles/libnet/mapfile-vers Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/mapfiles/libnet/mapfile-vers Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/mapfiles/libnio/mapfile-linux Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/mapfiles/libnio/mapfile-macosx Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/mapfiles/libnio/mapfile-solaris Wed Feb 24 08:58:31 2016 -0800
@@ -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/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java Wed Feb 24 08:58:31 2016 -0800
@@ -248,10 +248,7 @@
dir.mkdirs();
}
String className =
- (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" :
- "CLDRLocaleDataMetaInfo_" +
- CLDRConverter.DESTINATION_DIR.substring(CLDRConverter.DESTINATION_DIR.lastIndexOf('/')+1)
- .replaceAll("\\.", "_"));
+ (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : "CLDRLocaleDataMetaInfo");
File file = new File(dir, className + ".java");
if (!file.exists()) {
file.createNewFile();
--- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c Wed Feb 24 08:58:31 2016 -0800
@@ -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/lang/invoke/MethodHandleImpl.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -778,8 +778,21 @@
return (asTypeCache = wrapper);
}
+ // Customize target if counting happens for too long.
+ private int invocations = CUSTOMIZE_THRESHOLD;
+ private void maybeCustomizeTarget() {
+ int c = invocations;
+ if (c >= 0) {
+ if (c == 1) {
+ target.customize();
+ }
+ invocations = c - 1;
+ }
+ }
+
boolean countDown() {
int c = count;
+ maybeCustomizeTarget();
if (c <= 1) {
// Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility.
if (isCounting) {
--- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java Wed Feb 24 08:58:31 2016 -0800
@@ -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/java/nio/Bits.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/java/nio/Bits.java Wed Feb 24 08:58:31 2016 -0800
@@ -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
@@ -807,31 +807,131 @@
}
}
- static void copyFromCharArray(Object src, long srcPos, long dstAddr,
- long length)
- {
- copyFromShortArray(src, srcPos, dstAddr, length);
+ /**
+ * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
+ *
+ * @param src
+ * the source array, must be a 16-bit primitive array type
+ * @param srcPos
+ * byte offset within source array of the first element to read
+ * @param dstAddr
+ * destination address
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyFromCharArray(Object src, long srcPos, long dstAddr, long length) {
+ unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
}
- static void copyToCharArray(long srcAddr, Object dst, long dstPos,
- long length)
- {
- copyToShortArray(srcAddr, dst, dstPos, length);
+ /**
+ * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
+ *
+ * @param srcAddr
+ * source address
+ * @param dst
+ * destination array, must be a 16-bit primitive array type
+ * @param dstPos
+ * byte offset within the destination array of the first element to write
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyToCharArray(long srcAddr, Object dst, long dstPos, long length) {
+ unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
+ }
+
+ /**
+ * Copy and unconditionally byte swap 16 bit elements from a heap array to off-heap memory
+ *
+ * @param src
+ * the source array, must be a 16-bit primitive array type
+ * @param srcPos
+ * byte offset within source array of the first element to read
+ * @param dstAddr
+ * destination address
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyFromShortArray(Object src, long srcPos, long dstAddr, long length) {
+ unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 2);
+ }
+
+ /**
+ * Copy and unconditionally byte swap 16 bit elements from off-heap memory to a heap array
+ *
+ * @param srcAddr
+ * source address
+ * @param dst
+ * destination array, must be a 16-bit primitive array type
+ * @param dstPos
+ * byte offset within the destination array of the first element to write
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyToShortArray(long srcAddr, Object dst, long dstPos, long length) {
+ unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 2);
}
- static native void copyFromShortArray(Object src, long srcPos, long dstAddr,
- long length);
- static native void copyToShortArray(long srcAddr, Object dst, long dstPos,
- long length);
+ /**
+ * Copy and unconditionally byte swap 32 bit elements from a heap array to off-heap memory
+ *
+ * @param src
+ * the source array, must be a 32-bit primitive array type
+ * @param srcPos
+ * byte offset within source array of the first element to read
+ * @param dstAddr
+ * destination address
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyFromIntArray(Object src, long srcPos, long dstAddr, long length) {
+ unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 4);
+ }
+
+ /**
+ * Copy and unconditionally byte swap 32 bit elements from off-heap memory to a heap array
+ *
+ * @param srcAddr
+ * source address
+ * @param dst
+ * destination array, must be a 32-bit primitive array type
+ * @param dstPos
+ * byte offset within the destination array of the first element to write
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyToIntArray(long srcAddr, Object dst, long dstPos, long length) {
+ unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 4);
+ }
- static native void copyFromIntArray(Object src, long srcPos, long dstAddr,
- long length);
- static native void copyToIntArray(long srcAddr, Object dst, long dstPos,
- long length);
+ /**
+ * Copy and unconditionally byte swap 64 bit elements from a heap array to off-heap memory
+ *
+ * @param src
+ * the source array, must be a 64-bit primitive array type
+ * @param srcPos
+ * byte offset within source array of the first element to read
+ * @param dstAddr
+ * destination address
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyFromLongArray(Object src, long srcPos, long dstAddr, long length) {
+ unsafe.copySwapMemory(src, unsafe.arrayBaseOffset(src.getClass()) + srcPos, null, dstAddr, length, 8);
+ }
- static native void copyFromLongArray(Object src, long srcPos, long dstAddr,
- long length);
- static native void copyToLongArray(long srcAddr, Object dst, long dstPos,
- long length);
-
+ /**
+ * Copy and unconditionally byte swap 64 bit elements from off-heap memory to a heap array
+ *
+ * @param srcAddr
+ * source address
+ * @param dst
+ * destination array, must be a 64-bit primitive array type
+ * @param dstPos
+ * byte offset within the destination array of the first element to write
+ * @param length
+ * number of bytes to copy
+ */
+ static void copyToLongArray(long srcAddr, Object dst, long dstPos, long length) {
+ unsafe.copySwapMemory(null, srcAddr, dst, unsafe.arrayBaseOffset(dst.getClass()) + dstPos, length, 8);
+ }
}
--- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java Wed Feb 24 08:58:31 2016 -0800
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2014, 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
@@ -64,8 +64,7 @@
private static final Map<Provider, Object> verifyingProviders =
new IdentityHashMap<>();
- // Set the default value. May be changed in the static initializer.
- private static boolean isRestricted = true;
+ private static final boolean isRestricted;
/*
* Don't let anyone instantiate this.
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java Wed Feb 24 08:58:31 2016 -0800
@@ -279,6 +279,11 @@
public void handle(Signal sig) {
throw new UnsupportedOperationException("invoking native signal handle not supported");
}
+
+ public String toString() {
+ return this == SIG_DFL ? "SIG_DFL" :
+ (this == SIG_IGN ? "SIG_IGN" : super.toString());
+ }
}
}
--- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java Wed Feb 24 08:58:31 2016 -0800
@@ -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
@@ -458,6 +458,78 @@
copyMemory(null, srcAddress, null, destAddress, bytes);
}
+ private boolean isPrimitiveArray(Class<?> c) {
+ Class<?> componentType = c.getComponentType();
+ return componentType != null && componentType.isPrimitive();
+ }
+
+ private native void copySwapMemory0(Object srcBase, long srcOffset,
+ Object destBase, long destOffset,
+ long bytes, long elemSize);
+
+ /**
+ * Copies all elements from one block of memory to another block,
+ * *unconditionally* byte swapping the elements on the fly.
+ *
+ * <p>This method determines each block's base address by means of two parameters,
+ * and so it provides (in effect) a <em>double-register</em> addressing mode,
+ * as discussed in {@link #getInt(Object,long)}. When the object reference is null,
+ * the offset supplies an absolute base address.
+ *
+ * @since 9
+ */
+ public void copySwapMemory(Object srcBase, long srcOffset,
+ Object destBase, long destOffset,
+ long bytes, long elemSize) {
+ if (bytes < 0) {
+ throw new IllegalArgumentException();
+ }
+ if (elemSize != 2 && elemSize != 4 && elemSize != 8) {
+ throw new IllegalArgumentException();
+ }
+ if (bytes % elemSize != 0) {
+ throw new IllegalArgumentException();
+ }
+ if ((srcBase == null && srcOffset == 0) ||
+ (destBase == null && destOffset == 0)) {
+ throw new NullPointerException();
+ }
+
+ // Must be off-heap, or primitive heap arrays
+ if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) {
+ throw new IllegalArgumentException();
+ }
+ if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) {
+ throw new IllegalArgumentException();
+ }
+
+ // Sanity check size and offsets on 32-bit platforms. Most
+ // significant 32 bits must be zero.
+ if (ADDRESS_SIZE == 4 &&
+ (bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) {
+ throw new IllegalArgumentException();
+ }
+
+ if (bytes == 0) {
+ return;
+ }
+
+ copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize);
+ }
+
+ /**
+ * Copies all elements from one block of memory to another block, byte swapping the
+ * elements on the fly.
+ *
+ * This provides a <em>single-register</em> addressing mode, as
+ * discussed in {@link #getInt(Object,long)}.
+ *
+ * Equivalent to {@code copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize)}.
+ */
+ public void copySwapMemory(long srcAddress, long destAddress, long bytes, long elemSize) {
+ copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize);
+ }
+
/**
* Disposes of a block of native memory, as obtained from {@link
* #allocateMemory} or {@link #reallocateMemory}. The address passed to
@@ -1159,7 +1231,12 @@
/** @see #getLongUnaligned(Object, long) */
@HotSpotIntrinsicCandidate
public final char getCharUnaligned(Object o, long offset) {
- return (char)getShortUnaligned(o, offset);
+ if ((offset & 1) == 0) {
+ return getChar(o, offset);
+ } else {
+ return (char)makeShort(getByte(o, offset),
+ getByte(o, offset + 1));
+ }
}
/** @see #getLongUnaligned(Object, long, boolean) */
--- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/jdk/net/Sockets.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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/libjava/Bits.c Wed Feb 24 14:36:53 2016 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,233 +0,0 @@
-/*
- * Copyright (c) 2002, 2010, 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 "jni_util.h"
-#include "jlong.h"
-#include <string.h>
-
-#define MBYTE 1048576
-
-#define GETCRITICAL_OR_RETURN(bytes, env, obj) { \
- bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \
- if (bytes == NULL) { \
- if ((*env)->ExceptionOccurred(env) == NULL) \
- JNU_ThrowInternalError(env, "Unable to get array"); \
- return; \
- } \
-}
-
-#define RELEASECRITICAL(bytes, env, obj, mode) { \
- (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \
-}
-
-#define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff)))
-#define SWAPINT(x) ((jint)((SWAPSHORT((jshort)(x)) << 16) | \
- (SWAPSHORT((jshort)((x) >> 16)) & 0xffff)))
-#define SWAPLONG(x) ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \
- ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff)))
-
-JNIEXPORT void JNICALL
-Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jclass clazz, jobject src,
- jlong srcPos, jlong dstAddr, jlong length)
-{
- jbyte *bytes;
- size_t size;
- jshort *srcShort, *dstShort, *endShort;
- jshort tmpShort;
-
- dstShort = (jshort *)jlong_to_ptr(dstAddr);
-
- while (length > 0) {
- size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
-
- GETCRITICAL_OR_RETURN(bytes, env, src);
-
- srcShort = (jshort *)(bytes + srcPos);
- endShort = srcShort + (size / sizeof(jshort));
- while (srcShort < endShort) {
- tmpShort = *srcShort++;
- *dstShort++ = SWAPSHORT(tmpShort);
- }
-
- RELEASECRITICAL(bytes, env, src, JNI_ABORT);
-
- length -= size;
- srcPos += size;
- }
-}
-
-JNIEXPORT void JNICALL
-Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr,
- jobject dst, jlong dstPos, jlong length)
-{
- jbyte *bytes;
- size_t size;
- jshort *srcShort, *dstShort, *endShort;
- jshort tmpShort;
-
- srcShort = (jshort *)jlong_to_ptr(srcAddr);
-
- while (length > 0) {
- size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
-
- GETCRITICAL_OR_RETURN(bytes, env, dst);
-
- dstShort = (jshort *)(bytes + dstPos);
- endShort = srcShort + (size / sizeof(jshort));
- while (srcShort < endShort) {
- tmpShort = *srcShort++;
- *dstShort++ = SWAPSHORT(tmpShort);
- }
-
- RELEASECRITICAL(bytes, env, dst, 0);
-
- length -= size;
- dstPos += size;
- }
-}
-
-JNIEXPORT void JNICALL
-Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src,
- jlong srcPos, jlong dstAddr, jlong length)
-{
- jbyte *bytes;
- size_t size;
- jint *srcInt, *dstInt, *endInt;
- jint tmpInt;
-
- dstInt = (jint *)jlong_to_ptr(dstAddr);
-
- while (length > 0) {
- size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
-
- GETCRITICAL_OR_RETURN(bytes, env, src);
-
- srcInt = (jint *)(bytes + srcPos);
- endInt = srcInt + (size / sizeof(jint));
- while (srcInt < endInt) {
- tmpInt = *srcInt++;
- *dstInt++ = SWAPINT(tmpInt);
- }
-
- RELEASECRITICAL(bytes, env, src, JNI_ABORT);
-
- length -= size;
- srcPos += size;
- }
-}
-
-JNIEXPORT void JNICALL
-Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr,
- jobject dst, jlong dstPos, jlong length)
-{
- jbyte *bytes;
- size_t size;
- jint *srcInt, *dstInt, *endInt;
- jint tmpInt;
-
- srcInt = (jint *)jlong_to_ptr(srcAddr);
-
- while (length > 0) {
- size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
-
- GETCRITICAL_OR_RETURN(bytes, env, dst);
-
- dstInt = (jint *)(bytes + dstPos);
- endInt = srcInt + (size / sizeof(jint));
- while (srcInt < endInt) {
- tmpInt = *srcInt++;
- *dstInt++ = SWAPINT(tmpInt);
- }
-
- RELEASECRITICAL(bytes, env, dst, 0);
-
- length -= size;
- dstPos += size;
- }
-}
-
-JNIEXPORT void JNICALL
-Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src,
- jlong srcPos, jlong dstAddr, jlong length)
-{
- jbyte *bytes;
- size_t size;
- jlong *srcLong, *dstLong, *endLong;
- jlong tmpLong;
-
- dstLong = (jlong *)jlong_to_ptr(dstAddr);
-
- while (length > 0) {
- size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
-
- GETCRITICAL_OR_RETURN(bytes, env, src);
-
- srcLong = (jlong *)(bytes + srcPos);
- endLong = srcLong + (size / sizeof(jlong));
- while (srcLong < endLong) {
- tmpLong = *srcLong++;
- *dstLong++ = SWAPLONG(tmpLong);
- }
-
- RELEASECRITICAL(bytes, env, src, JNI_ABORT);
-
- length -= size;
- srcPos += size;
- }
-}
-
-JNIEXPORT void JNICALL
-Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr,
- jobject dst, jlong dstPos, jlong length)
-{
- jbyte *bytes;
- size_t size;
- jlong *srcLong, *dstLong, *endLong;
- jlong tmpLong;
-
- srcLong = (jlong *)jlong_to_ptr(srcAddr);
-
- while (length > 0) {
- size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE;
-
- GETCRITICAL_OR_RETURN(bytes, env, dst);
-
- dstLong = (jlong *)(bytes + dstPos);
- endLong = srcLong + (size / sizeof(jlong));
- while (srcLong < endLong) {
- tmpLong = *srcLong++;
- *dstLong++ = SWAPLONG(tmpLong);
- }
-
- RELEASECRITICAL(bytes, env, dst, 0);
-
- length -= size;
- dstPos += size;
- }
-}
--- a/jdk/src/java.base/share/native/libnet/net_util.c Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/native/libnet/net_util.c Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/native/libnet/net_util.h Wed Feb 24 08:58:31 2016 -0800
@@ -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/share/native/libzip/CRC32.c Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/share/native/libzip/CRC32.c Wed Feb 24 08:58:31 2016 -0800
@@ -54,7 +54,7 @@
return crc;
}
-JNIEXPORT jint JNICALL
+jint JNICALL
ZIP_CRC32(jint crc, const jbyte *buf, jint len)
{
return crc32(crc, (Bytef*)buf, len);
--- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/native/libnet/SdpSupport.c Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c Wed Feb 24 08:58:31 2016 -0800
@@ -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/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo Wed Feb 24 08:58:31 2016 -0800
@@ -1,2 +1,2 @@
sun.util.resources.provider.NonBaseLocaleDataMetaInfo
-sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo_jdk_localedata
+sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo
--- a/jdk/test/java/net/SocketOption/OptionsTest.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/test/java/net/SocketOption/OptionsTest.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java Wed Feb 24 08:58:31 2016 -0800
@@ -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 {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java Wed Feb 24 08:58:31 2016 -0800
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ *
+ * 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 8149417
+ * @summary Use final restricted flag
+ */
+
+import java.security.*;
+import java.lang.reflect.*;
+
+public class FinalRestricted {
+
+ public static void main(String[] args) throws Exception {
+
+ int modifiers = Class.forName("javax.crypto.JceSecurity")
+ .getDeclaredField("isRestricted").getModifiers();
+ if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers) &&
+ Modifier.isPrivate(modifiers))) {
+ throw new Exception("JceSecurity.isRestricted is not " +
+ "a private static final field!");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java Wed Feb 24 08:58:31 2016 -0800
@@ -0,0 +1,711 @@
+/*
+ * 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.
+ *
+ * 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.internal.misc.Unsafe;
+import java.lang.reflect.Field;
+
+/*
+ * @test
+ * @summary Test Unsafe.copySwapMemory
+ * @modules java.base/jdk.internal.misc
+ */
+public class CopySwap {
+ private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG");
+
+ public static final long KB = 1024;
+ public static final long MB = KB * 1024;
+ public static final long GB = MB * 1024;
+
+ private static final Unsafe UNSAFE;
+ private static final int SMALL_COPY_SIZE = 32;
+ private static final int BASE_ALIGNMENT = 16;
+
+ static {
+ try {
+ Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe");
+ f.setAccessible(true);
+ UNSAFE = (jdk.internal.misc.Unsafe) f.get(null);
+ } catch (Exception e) {
+ throw new RuntimeException("Unable to get Unsafe instance.", e);
+ }
+ }
+
+ private static long alignDown(long value, long alignment) {
+ return value & ~(alignment - 1);
+ }
+
+ private static long alignUp(long value, long alignment) {
+ return (value + alignment - 1) & ~(alignment - 1);
+ }
+
+ private static boolean isAligned(long value, long alignment) {
+ return value == alignDown(value, alignment);
+ }
+
+ private CopySwap() {
+ }
+
+ /**
+ * Generate verification data for a given offset
+ *
+ * The verification data is used to verify that the correct bytes
+ * have indeed been copied and byte swapped.
+ *
+ * The data is generated based on the offset (in bytes) into the
+ * source buffer. For a native buffer the offset is relative to
+ * the base pointer. For a heap array it is relative to the
+ * address of the first array element.
+ *
+ * This method will return the result of doing an elementSize byte
+ * read starting at offset (in bytes).
+ *
+ * @param offset offset into buffer
+ * @param elemSize size (in bytes) of the element
+ *
+ * @return the verification data, only the least significant
+ * elemSize*8 bits are set, zero extended
+ */
+ private long getVerificationDataForOffset(long offset, long elemSize) {
+ byte[] bytes = new byte[(int)elemSize];
+
+ for (long i = 0; i < elemSize; i++) {
+ bytes[(int)i] = (byte)(offset + i);
+ }
+
+ long o = UNSAFE.arrayBaseOffset(byte[].class);
+
+ switch ((int)elemSize) {
+ case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o));
+ case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o));
+ case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o));
+ case 8: return UNSAFE.getLongUnaligned(bytes, o);
+ default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
+ }
+ }
+
+ /**
+ * Verify byte swapped data
+ *
+ * @param ptr the data to verify
+ * @param srcOffset the srcOffset (in bytes) from which the copy started,
+ * used as key to regenerate the verification data
+ * @param dstOffset the offset (in bytes) in the array at which to start
+ * the verification, relative to the first element in the array
+ * @param size size (in bytes) of data to to verify
+ * @param elemSize size (in bytes) of the individual array elements
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) {
+ for (long offset = 0; offset < size; offset += elemSize) {
+ long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize);
+ long expected = byteSwap(expectedUnswapped, elemSize);
+
+ long actual = getArrayElem(ptr, dstOffset + offset, elemSize);
+
+ if (expected != actual) {
+ throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) +
+ " dstOffset: 0x" + Long.toHexString(dstOffset) +
+ " size: 0x" + Long.toHexString(size) +
+ " offset: 0x" + Long.toHexString(offset) +
+ " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) +
+ " expected: 0x" + Long.toHexString(expected) +
+ " != actual: 0x" + Long.toHexString(actual));
+ }
+ }
+ }
+
+ /**
+ * Initialize an array with verification friendly data
+ *
+ * @param ptr pointer to the data to initialize
+ * @param size size (in bytes) of the data
+ * @param elemSize size (in bytes) of the individual elements
+ */
+ private void initVerificationData(GenericPointer ptr, long size, long elemSize) {
+ for (long offset = 0; offset < size; offset++) {
+ byte data = (byte)getVerificationDataForOffset(offset, 1);
+
+ if (ptr.isOnHeap()) {
+ UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data);
+ } else {
+ UNSAFE.putByte(ptr.getOffset() + offset, data);
+ }
+ }
+ }
+
+ /**
+ * Allocate a primitive array
+ *
+ * @param size size (in bytes) of all the array elements (elemSize * length)
+ * @param elemSize the size of the array elements
+ *
+ * @return a newly allocated primitive array
+ */
+ Object allocArray(long size, long elemSize) {
+ int length = (int)(size / elemSize);
+
+ switch ((int)elemSize) {
+ case 2: return new short[length];
+ case 4: return new int[length];
+ case 8: return new long[length];
+ default:
+ throw new IllegalArgumentException("Invalid element size: " + elemSize);
+ }
+ }
+
+ /**
+ * Get the value of a primitive array entry
+ *
+ * @param ptr pointer to the data
+ * @param offset offset (in bytes) of the array element, relative to the first element in the array
+ *
+ * @return the array element, as an unsigned long
+ */
+ private long getArrayElem(GenericPointer ptr, long offset, long elemSize) {
+ if (ptr.isOnHeap()) {
+ Object o = ptr.getObject();
+ int index = (int)(offset / elemSize);
+
+ if (o instanceof short[]) {
+ short[] arr = (short[])o;
+ return Short.toUnsignedLong(arr[index]);
+ } else if (o instanceof int[]) {
+ int[] arr = (int[])o;
+ return Integer.toUnsignedLong(arr[index]);
+ } else if (o instanceof long[]) {
+ long[] arr = (long[])o;
+ return arr[index];
+ } else {
+ throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
+ }
+ } else {
+ long addr = ptr.getOffset() + offset;
+
+ switch ((int)elemSize) {
+ case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr));
+ case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr));
+ case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr));
+ case 8: return UNSAFE.getLongUnaligned(null, addr);
+ default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
+ }
+ }
+ }
+
+ private void putValue(long addr, long elemSize, long value) {
+ switch ((int)elemSize) {
+ case 1: UNSAFE.putByte(addr, (byte)value); break;
+ case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break;
+ case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break;
+ case 8: UNSAFE.putLongUnaligned(null, addr, value); break;
+ default: throw new IllegalArgumentException("Invalid element size: " + elemSize);
+ }
+ }
+
+ /**
+ * Get the size of the elements for an array
+ *
+ * @param o a primitive heap array
+ *
+ * @return the size (in bytes) of the individual array elements
+ */
+ private long getArrayElemSize(Object o) {
+ if (o instanceof short[]) {
+ return 2;
+ } else if (o instanceof int[]) {
+ return 4;
+ } else if (o instanceof long[]) {
+ return 8;
+ } else {
+ throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName());
+ }
+ }
+
+ /**
+ * Byte swap a value
+ *
+ * @param value the value to swap, only the bytes*8 least significant bits are used
+ * @param size size (in bytes) of the value
+ *
+ * @return the byte swapped value in the bytes*8 least significant bits
+ */
+ private long byteSwap(long value, long size) {
+ switch ((int)size) {
+ case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value));
+ case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value));
+ case 8: return Long.reverseBytes(value);
+ default: throw new IllegalArgumentException("Invalid element size: " + size);
+ }
+ }
+
+ /**
+ * Verify data in a heap array which has *not* been byte swapped
+ *
+ * @param ptr the data to verify
+ * @param startOffset the offset (in bytes) at which to start the verification
+ * @param size size (in bytes) of the data to verify
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) {
+ for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) {
+ byte expected = (byte)getVerificationDataForOffset(elemOffset, 1);
+
+ byte actual;
+ if (ptr.isOnHeap()) {
+ actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset);
+ } else {
+ actual = UNSAFE.getByte(ptr.getOffset() + elemOffset);
+ }
+
+ if (expected != actual) {
+ throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) +
+ " size: 0x" + Long.toHexString(size) +
+ " elemOffset: 0x" + Long.toHexString(elemOffset) +
+ " expected: 0x" + Long.toHexString(expected) +
+ " != actual: 0x" + Long.toHexString(actual));
+ }
+ }
+ }
+
+
+ /**
+ * Copy and byte swap data from the source to the destination
+ *
+ * This method will pre-populate the whole source and destination
+ * buffers with verification friendly data. It will then use
+ * copySwapMemory to fill part of the destination buffer with
+ * swapped data from the source. Some space (padding) will be
+ * left before and after the data in the destination buffer, which
+ * should not be touched/overwritten by the copy call.
+ *
+ * Note: Both source and destination buffers will be overwritten!
+ *
+ * @param src source buffer to copy from
+ * @param srcOffset the offset (in bytes) in the source buffer, relative to
+ * the first array element, at which to start reading data
+ * @param dst destination buffer to copy to
+ * @param dstOffset the offset (in bytes) in the destination
+ * buffer, relative to the first array element, at which to
+ * start writing data
+ * @param bufSize the size (in bytes) of the src and dst arrays
+ * @param copyBytes the size (in bytes) of the copy to perform,
+ * must be a multiple of elemSize
+ * @param elemSize the size (in bytes) of the elements to byte swap
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void testCopySwap(GenericPointer src, long srcOffset,
+ GenericPointer dst, long dstOffset,
+ long bufSize, long copyBytes, long elemSize) {
+ if (!isAligned(copyBytes, elemSize)) {
+ throw new IllegalArgumentException(
+ "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")");
+ }
+ if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) {
+ throw new IllegalArgumentException(
+ "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")");
+ }
+ if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) {
+ throw new IllegalArgumentException(
+ "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")");
+ }
+ if (srcOffset + copyBytes > bufSize) {
+ throw new IllegalArgumentException(
+ "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
+ }
+ if (dstOffset + copyBytes > bufSize) {
+ throw new IllegalArgumentException(
+ "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")");
+ }
+
+ // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes)
+ initVerificationData(src, bufSize, elemSize);
+ if (!src.equals(dst)) {
+ initVerificationData(dst, bufSize, elemSize);
+ }
+
+ if (DEBUG) {
+ System.out.println("===before===");
+ for (int offset = 0; offset < bufSize; offset += elemSize) {
+ long srcValue = getArrayElem(src, offset, elemSize);
+ long dstValue = getArrayElem(dst, offset, elemSize);
+
+ System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
+ " src=0x" + Long.toHexString(srcValue) +
+ " dst=0x" + Long.toHexString(dstValue));
+ }
+ }
+
+ // Copy & swap data into the middle of the destination buffer
+ UNSAFE.copySwapMemory(src.getObject(),
+ src.getOffset() + srcOffset,
+ dst.getObject(),
+ dst.getOffset() + dstOffset,
+ copyBytes,
+ elemSize);
+
+ if (DEBUG) {
+ System.out.println("===after===");
+ for (int offset = 0; offset < bufSize; offset += elemSize) {
+ long srcValue = getArrayElem(src, offset, elemSize);
+ long dstValue = getArrayElem(dst, offset, elemSize);
+
+ System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) +
+ " src=0x" + Long.toHexString(srcValue) +
+ " dst=0x" + Long.toHexString(dstValue));
+ }
+ }
+
+ // Verify the the front padding is unchanged
+ verifyUnswappedData(dst, 0, dstOffset);
+
+ // Verify swapped data
+ verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize);
+
+ // Verify that the back back padding is unchanged
+ long frontAndDataBytes = dstOffset + copyBytes;
+ long trailingBytes = bufSize - frontAndDataBytes;
+ verifyUnswappedData(dst, frontAndDataBytes, trailingBytes);
+ }
+
+ /**
+ * Test various configurations copy-swapping from one buffer to the other
+ *
+ * @param src the source buffer to copy from
+ * @param dst the destination buffer to copy to
+ * @param size size (in bytes) of the buffers
+ * @param elemSize size (in bytes) of the individual elements
+ *
+ * @throws RuntimeException if an error is found
+ */
+ public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) {
+ // offset in source from which to start reading data
+ for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) {
+
+ // offset in destination at which to start writing data
+ for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) {
+
+ // number of bytes to copy
+ long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset);
+ for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) {
+ try {
+ testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize);
+ } catch (RuntimeException e) {
+ // Wrap the exception in another exception to catch the relevant configuration data
+ throw new RuntimeException("testBufferPair: " +
+ "src=" + src +
+ " dst=" + dst +
+ " elemSize=0x" + Long.toHexString(elemSize) +
+ " copyBytes=0x" + Long.toHexString(copyBytes) +
+ " srcOffset=0x" + Long.toHexString(srcOffset) +
+ " dstOffset=0x" + Long.toHexString(dstOffset),
+ e);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Test copying between various permutations of buffers
+ *
+ * @param buffers buffers to permute (src x dst)
+ * @param size size (in bytes) of buffers
+ * @param elemSize size (in bytes) of individual elements
+ *
+ * @throws RuntimeException if an error is found
+ */
+ public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) {
+ for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) {
+ for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) {
+ testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize);
+ }
+ }
+ }
+
+ /**
+ * Test copying of a specific element size
+ *
+ * @param size size (in bytes) of buffers to allocate
+ * @param elemSize size (in bytes) of individual elements
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void testElemSize(long size, long elemSize) {
+ long buf1Raw = 0;
+ long buf2Raw = 0;
+
+ try {
+ buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
+ long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT);
+
+ buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
+ long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT);
+
+ GenericPointer[] buffers = {
+ new GenericPointer(buf1),
+ new GenericPointer(buf2),
+ new GenericPointer(allocArray(size, elemSize)),
+ new GenericPointer(allocArray(size, elemSize))
+ };
+
+ testPermuteBuffers(buffers, size, elemSize);
+ } finally {
+ if (buf1Raw != 0) {
+ UNSAFE.freeMemory(buf1Raw);
+ }
+ if (buf2Raw != 0) {
+ UNSAFE.freeMemory(buf2Raw);
+ }
+ }
+ }
+
+ /**
+ * Verify that small copy swaps work
+ */
+ private void testSmallCopy() {
+ int smallBufSize = SMALL_COPY_SIZE;
+
+ // Test various element types and heap/native combinations
+ for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) {
+ testElemSize(smallBufSize, elemSize);
+ }
+ }
+
+
+ /**
+ * Verify that large copy swaps work
+ */
+ private void testLargeCopy() {
+ long size = 2 * GB + 8;
+ long bufRaw = 0;
+
+ // Check that a large native copy succeeds
+ try {
+ try {
+ bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT);
+ } catch (OutOfMemoryError e) {
+ // Accept failure, skip test
+ return;
+ }
+
+ long buf = alignUp(bufRaw, BASE_ALIGNMENT);
+
+ UNSAFE.copySwapMemory(null, buf, null, buf, size, 8);
+ } catch (Exception e) {
+ throw new RuntimeException("copySwapMemory of large buffer failed");
+ } finally {
+ if (bufRaw != 0) {
+ UNSAFE.freeMemory(bufRaw);
+ }
+ }
+ }
+
+ /**
+ * Run positive tests
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void testPositive() {
+ testSmallCopy();
+ testLargeCopy();
+ }
+
+ /**
+ * Run negative tests, testing corner cases and the various exceptions
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void testNegative() {
+ long bufRaw = 0;
+
+ try {
+ bufRaw = UNSAFE.allocateMemory(1024);
+ long buf = alignUp(bufRaw, BASE_ALIGNMENT);
+ short[] arr = new short[16];
+
+ // Check various illegal element sizes
+ for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) {
+ long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 };
+ for (long size : illegalSizes) {
+ try {
+ // Check that illegal elemSize throws an IAE
+ UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize);
+ throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize);
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+ }
+
+ try {
+ // Check that negative srcOffset throws an IAE
+ UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2);
+ throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1");
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+
+ try {
+ // Check that negative dstOffset throws an IAE
+ UNSAFE.copySwapMemory(arr, UNSAFE.arrayBaseOffset(arr.getClass()), arr, -1, 16, 2);
+ throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset=-1");
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+
+ long illegalElemSizes[] = { 0, 1, 3, 5, 6, 7, 9, 10, -1 };
+ for (long elemSize : illegalElemSizes) {
+ try {
+ // Check that elemSize 1 throws an IAE
+ UNSAFE.copySwapMemory(null, buf, null, buf, 16, elemSize);
+ throw new RuntimeException("copySwapMemory failed to throw NPE");
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+
+ try {
+ // Check that a NULL source throws NPE
+ UNSAFE.copySwapMemory(null, 0, null, buf, 16, 2);
+ throw new RuntimeException("copySwapMemory failed to throw NPE");
+ } catch (NullPointerException e) {
+ // good
+ }
+
+ try {
+ // Check that a NULL destination throws NPE
+ UNSAFE.copySwapMemory(null, buf, null, 0, 16, 2);
+ throw new RuntimeException("copySwapMemory failed to throw NPE");
+ } catch (NullPointerException e) {
+ // good
+ }
+
+ try {
+ // Check that a reference array destination throws IAE
+ UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8);
+ throw new RuntimeException("copySwapMemory failed to throw NPE");
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+
+ // Check that invalid source & dest pointers throw IAEs (only relevant on 32-bit platforms)
+ if (UNSAFE.addressSize() == 4) {
+ long invalidPtr = (long)1 << 35; // Pick a random bit in upper 32 bits
+
+ try {
+ // Check that an invalid (not 32-bit clean) source pointer throws IAE
+ UNSAFE.copySwapMemory(null, invalidPtr, null, buf, 16, 2);
+ throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset 0x" +
+ Long.toHexString(invalidPtr));
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+
+ try {
+ // Check that an invalid (not 32-bit clean) source pointer throws IAE
+ UNSAFE.copySwapMemory(null, buf, null, invalidPtr, 16, 2);
+ throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset 0x" +
+ Long.toHexString(invalidPtr));
+ } catch (IllegalArgumentException e) {
+ // good
+ }
+ }
+ } finally {
+ if (bufRaw != 0) {
+ UNSAFE.freeMemory(bufRaw);
+ }
+ }
+ }
+
+ /**
+ * Run all tests
+ *
+ * @throws RuntimeException if an error is found
+ */
+ private void test() {
+ testPositive();
+ testNegative();
+ }
+
+ public static void main(String[] args) {
+ CopySwap cs = new CopySwap();
+ cs.test();
+ }
+
+ /**
+ * Helper class to represent a "pointer" - either a heap array or
+ * a pointer to a native buffer.
+ *
+ * In the case of a native pointer, the Object is null and the offset is
+ * the absolute address of the native buffer.
+ *
+ * In the case of a heap object, the Object is a primitive array, and
+ * the offset will be set to the base offset to the first element, meaning
+ * the object and the offset together form a double-register pointer.
+ */
+ static class GenericPointer {
+ private final Object o;
+ private final long offset;
+
+ private GenericPointer(Object o, long offset) {
+ this.o = o;
+ this.offset = offset;
+ }
+
+ public String toString() {
+ return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")";
+ }
+
+ public boolean equals(Object other) {
+ if (!(other instanceof GenericPointer)) {
+ return false;
+ }
+
+ GenericPointer otherp = (GenericPointer)other;
+
+ return o == otherp.o && offset == otherp.offset;
+ }
+
+ GenericPointer(Object o) {
+ this(o, UNSAFE.arrayBaseOffset(o.getClass()));
+ }
+
+ GenericPointer(long offset) {
+ this(null, offset);
+ }
+
+ public boolean isOnHeap() {
+ return o != null;
+ }
+
+ public Object getObject() {
+ return o;
+ }
+
+ public long getOffset() {
+ return offset;
+ }
+ }
+}
--- a/jdk/test/sun/misc/SunMiscSignalTest.java Wed Feb 24 14:36:53 2016 +0300
+++ b/jdk/test/sun/misc/SunMiscSignalTest.java Wed Feb 24 08:58:31 2016 -0800
@@ -180,6 +180,12 @@
return newArray;
}
+ // Return true if the signal is one of the shutdown signals known to the VM
+ private static boolean isShutdownSignal(Signal signal) {
+ String name = signal.getName();
+ return name.equals("INT") || name.equals("HUP") || name.equals("TERM");
+ }
+
/**
* Quick verification of supported signals using sun.misc.Signal.
*
@@ -201,14 +207,24 @@
Assert.assertEquals(signal.toString(), "SIG" + name, "toString() mismatch, ");
try {
- SignalHandler old = Signal.handle(signal, h);
+ orig = Signal.handle(signal, h);
+ printf("oldHandler: %s%n", orig);
Assert.assertEquals(CanRegister.YES, register, "Unexpected handle succeeded " + name);
try {
Signal.raise(signal);
Assert.assertEquals(CanRaise.YES, raise, "Unexpected raise success for " + name);
Invoked inv = h.semaphore().tryAcquire(Utils.adjustTimeout(100L),
TimeUnit.MILLISECONDS) ? Invoked.YES : Invoked.NO;
- Assert.assertEquals(inv, invoked, "handler not invoked;");
+ if (!isShutdownSignal(signal)) {
+ // Normal case
+ Assert.assertEquals(inv, invoked, "handler not invoked;");
+ } else {
+ if (orig == SignalHandler.SIG_IGN) {
+ Assert.assertEquals(inv, Invoked.NO, "handler should not be invoked");
+ } else {
+ Assert.assertEquals(inv, invoked, "handler not invoked;");
+ }
+ }
} catch (IllegalArgumentException uoe3) {
Assert.assertNotEquals(CanRaise.YES, raise, "raise failed for " + name +
": " + uoe3.getMessage());
@@ -270,14 +286,22 @@
}
// Test expected exception when raising a signal when no handler defined
- @Test(expectedExceptions = IllegalArgumentException.class)
+ @Test
static void testRaiseNoConsumer() {
Signal signal = new Signal("INT");
SignalHandler orig = null;
try {
- Signal.handle(signal, SignalHandler.SIG_DFL);
+ orig = Signal.handle(signal, SignalHandler.SIG_DFL);
+ printf("oldHandler: %s%n", orig);
+ if (orig == SignalHandler.SIG_IGN) {
+ // SIG_IGN for TERM means it cannot be handled
+ return;
+ }
Signal.raise(signal);
- } finally {
+ Assert.fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException iae) {
+ printf("IAE message: %s%n", iae.getMessage());
+ } finally {
// Restore original signal handler
if (orig != null && signal != null) {
Signal.handle(signal, orig);
@@ -296,7 +320,13 @@
}
Handler handler = new Handler();
Signal signal = new Signal("INT");
- Signal.handle(signal, handler);
+ SignalHandler orig = Signal.handle(signal, handler);
+ printf("oldHandler: %s%n", orig);
+ if (orig == SignalHandler.SIG_IGN) {
+ // SIG_IGN for INT means it cannot be handled
+ return;
+ }
+
Signal.raise(signal);
boolean handled = handler.semaphore()
.tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS);
@@ -332,6 +362,10 @@
Handler h1 = new Handler();
Handler h2 = new Handler();
SignalHandler orig = Signal.handle(signal, h1);
+ if (orig == SignalHandler.SIG_IGN) {
+ // SIG_IGN for TERM means it cannot be handled
+ return;
+ }
try {
SignalHandler prev = Signal.handle(signal, h2);