changeset 13784:d1974f961903

Merge
author lana
date Thu, 25 Feb 2016 11:27:30 -0800
parents b84b5f6d9ed5 f9913ea0f95c
children e0da6c2a5c32
files src/java.base/share/native/libjava/Bits.c
diffstat 83 files changed, 3385 insertions(+), 487 deletions(-) [+]
line wrap: on
line diff
--- a/make/gensrc/GensrcMisc.gmk	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/gensrc/GensrcMisc.gmk	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -53,6 +53,8 @@
 $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \
     SRC := $(GENSRC_SOR_SRC), \
     INCLUDE_FILES := $(GENSRC_SOR_SRC_FILE), \
+    CFLAGS_windows := -nologo, \
+    LDFLAGS_windows := -nologo, \
     TOOLCHAIN := TOOLCHAIN_BUILD, \
     OBJECT_DIR := $(GENSRC_SOR_BIN), \
     OUTPUT_DIR := $(GENSRC_SOR_BIN), \
@@ -61,12 +63,12 @@
 SOR_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/ch/SocketOptionRegistry-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template
 
 ifeq ($(wildcard $(SOR_PREGEN_FILE)), )
-  $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE)
+  $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE_TARGET)
 	$(MKDIR) -p $(@D)
 	$(RM) $@ $@.tmp
 	NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \
 	    $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOR_COPYRIGHT_YEARS)" > $@.tmp
-	$(BUILD_GENSRC_SOR_EXE) >> $@.tmp
+	$(BUILD_GENSRC_SOR_EXE_TARGET) >> $@.tmp
 	$(MV) $@.tmp $@
 else
   $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(SOR_PREGEN_FILE)
@@ -97,12 +99,12 @@
   UC_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/fs/UnixConstants-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template
 
   ifeq ($(wildcard $(UC_PREGEN_FILE)), )
-    $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE)
+    $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE_TARGET)
 	$(MKDIR) -p $(@D)
 	$(RM) $@ $@.tmp
 	NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \
 	    $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(UC_COPYRIGHT_YEARS)" > $@.tmp
-	$(BUILD_GENSRC_UC_EXE) >> $@.tmp
+	$(BUILD_GENSRC_UC_EXE_TARGET) >> $@.tmp
 	$(MV) $@.tmp $@
   else
     $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(UC_PREGEN_FILE)
@@ -132,12 +134,12 @@
       OUTPUT_DIR := $(GENSRC_SOL_BIN), \
       PROGRAM := genSolarisConstants))
 
-  $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE)
+  $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE_TARGET)
 	$(MKDIR) -p $(@D)
 	$(RM) $@ $@.tmp
 	NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \
 	    $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOL_COPYRIGHT_YEARS)" > $@.tmp
-	$(BUILD_GENSRC_SOL_EXE) >> $@.tmp
+	$(BUILD_GENSRC_SOL_EXE_TARGET) >> $@.tmp
 	$(MV) $@.tmp $@
 
 
--- a/make/lib/Awt2dLibraries.gmk	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/lib/Awt2dLibraries.gmk	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -593,8 +593,8 @@
         LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \
         REORDER := $(LIBAWT_HEADLESS_REORDER), \
         LIBS_unix := -lawt -ljvm -ljava, \
-        LIBS_linux := -lm $(LIBDL), \
-        LIBS_solaris := -lm $(LIBDL) $(LIBCXX) -lc, \
+        LIBS_linux := $(LIBM) $(LIBDL), \
+        LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \
         OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \
     ))
 
--- a/make/lib/CoreLibraries.gmk	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/lib/CoreLibraries.gmk	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -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), \
@@ -163,7 +157,7 @@
     LIBS_unix := -ljvm -lverify, \
     LIBS_linux := $(LIBDL) $(BUILD_LIBFDLIBM), \
     LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL) $(BUILD_LIBFDLIBM) -lc, \
-    LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) -lm,\
+    LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) $(LIBM),\
     LIBS_macosx := -lfdlibm \
         -framework CoreFoundation \
         -framework Foundation \
--- a/make/lib/Lib-java.instrument.gmk	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/lib/Lib-java.instrument.gmk	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -67,7 +67,6 @@
         -L$(call FindLibDirForModule, java.base)/jli, \
     LDFLAGS_macosx := -Wl$(COMMA)-all_load, \
     LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \
-    LDFLAGS_windows := -export:Agent_OnAttach, \
     LIBS := $(JDKLIB_LIBS), \
     LIBS_unix := -ljava $(LIBZ), \
     LIBS_linux := -ljli $(LIBDL), \
--- a/make/lib/Lib-jdk.jdi.gmk	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/lib/Lib-jdk.jdi.gmk	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -47,7 +47,6 @@
       CFLAGS := $(CFLAGS_JDKLIB) -DUSE_MMAP \
           $(LIBDT_SHMEM_CPPFLAGS), \
       LDFLAGS := $(LDFLAGS_JDKLIB), \
-      LDFLAGS_windows := -export:jdwpTransport_OnLoad, \
       LIBS := $(JDKLIB_LIBS), \
       VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
       RC_FLAGS := $(RC_FLAGS) \
--- a/make/lib/Lib-jdk.jdwp.agent.gmk	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/lib/Lib-jdk.jdwp.agent.gmk	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -46,7 +46,6 @@
     MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdt_socket/mapfile-vers, \
     LDFLAGS := $(LDFLAGS_JDKLIB) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
-    LDFLAGS_windows := -export:jdwpTransport_OnLoad, \
     LIBS_linux := -lpthread, \
     LIBS_solaris := -lnsl -lsocket -lc, \
     LIBS_windows := $(JDKLIB_LIBS) ws2_32.lib, \
--- a/make/mapfiles/libjava/mapfile-vers	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/mapfiles/libjava/mapfile-vers	Thu Feb 25 11:27:30 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/make/mapfiles/libnet/mapfile-vers	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/mapfiles/libnet/mapfile-vers	Thu Feb 25 11:27:30 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/make/mapfiles/libnio/mapfile-linux	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/mapfiles/libnio/mapfile-linux	Thu Feb 25 11:27:30 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/make/mapfiles/libnio/mapfile-macosx	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/mapfiles/libnio/mapfile-macosx	Thu Feb 25 11:27:30 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/make/mapfiles/libnio/mapfile-solaris	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/mapfiles/libnio/mapfile-solaris	Thu Feb 25 11:27:30 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/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java	Thu Feb 25 11:27:30 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/make/src/classes/build/tools/dtdbuilder/DTDParser.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/src/classes/build/tools/dtdbuilder/DTDParser.java	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, 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
@@ -908,16 +908,12 @@
             this.dtd = dtd;
             this.in = new DTDInputStream(in, dtd);
 
-            long tm = System.currentTimeMillis();
             ch = this.in.read();
             parseSection();
 
             if (ch != -1) {
                 error("premature");
             }
-
-            tm = System.currentTimeMillis() - tm;
-            System.err.println("[Parsed DTD " + dtd + " in " + tm + "ms]");
         } catch (IOException e) {
             error("ioexception");
         } catch (Exception e) {
--- a/make/src/native/genconstants/ch/genSocketOptionRegistry.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/make/src/native/genconstants/ch/genSocketOptionRegistry.c	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandle.java	Thu Feb 25 11:27:30 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
@@ -1026,6 +1026,9 @@
   .asCollector(long[].class, 1);
 assertEquals("[123]", (String) longsToString.invokeExact((long)123));
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
      * @param arrayLength the number of arguments to collect into a new array argument
      * @return a new method handle which collects some trailing argument
@@ -1067,6 +1070,9 @@
     swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1);
     assertEquals("BCPQRSZ", swr.toString());
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param collectArgPos the zero-based position in the parameter list at which to start collecting.
      * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments
      * @param arrayLength the number of arguments to collect into a new array argument
@@ -1356,8 +1362,11 @@
      * The reference {@code x} must be convertible to the first parameter
      * type of the target.
      * <p>
-     * (<em>Note:</em>  Because method handles are immutable, the target method handle
-     * retains its original type and behavior.)
+     * <em>Note:</em>  Because method handles are immutable, the target method handle
+     * retains its original type and behavior.
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param x  the value to bind to the first argument of the target
      * @return a new method handle which prepends the given value to the incoming
      *         argument list, before calling the original method handle
--- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java	Thu Feb 25 11:27:30 2016 -0800
@@ -2139,7 +2139,7 @@
      * if its index does not appear in the array.
      * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments},
      * incoming arguments which are not mentioned in the reordering array
-     * are may be any type, as determined only by {@code newType}.
+     * may be of any type, as determined only by {@code newType}.
      * <blockquote><pre>{@code
 import static java.lang.invoke.MethodHandles.*;
 import static java.lang.invoke.MethodType.*;
@@ -2157,6 +2157,9 @@
 assert(twice.type().equals(intfn1));
 assert((int)twice.invokeExact(21) == 42);
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param target the method handle to invoke after arguments are reordered
      * @param newType the expected type of the new method handle
      * @param reorder an index array which controls the reordering
@@ -2421,6 +2424,9 @@
      * It may range between zero and <i>N-L</i> (inclusively),
      * where <i>N</i> is the arity of the target method handle
      * and <i>L</i> is the length of the values array.
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param target the method handle to invoke after the argument is inserted
      * @param pos where to insert the argument (zero for the first)
      * @param values the series of arguments to insert
@@ -2639,14 +2645,25 @@
 MethodHandle f2 = filterArguments(cat, 0, upcase, upcase);
 assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * denotes the return type of both the {@code target} and resulting adapter.
+     * {@code P}/{@code p} and {@code B}/{@code b} represent the types and values
+     * of the parameters and arguments that precede and follow the filter position
+     * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types and
+     * values of the filtered parameters and arguments; they also represent the
+     * return types of the {@code filter[i]} handles. The latter accept arguments
+     * {@code v[i]} of type {@code V[i]}, which also appear in the signature of
+     * the resulting adapter.
      * <blockquote><pre>{@code
-     * V target(P... p, A[i]... a[i], B... b);
+     * T target(P... p, A[i]... a[i], B... b);
      * A[i] filter[i](V[i]);
      * T adapter(P... p, V[i]... v[i], B... b) {
-     *   return target(p..., f[i](v[i])..., b...);
+     *   return target(p..., filter[i](v[i])..., b...);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      *
      * @param target the method handle to invoke after arguments are filtered
      * @param pos the position of the first argument to filter
@@ -2753,7 +2770,17 @@
 assertEquals("[top, [[up, down, strange], charm], bottom]",
              (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom"));
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the return type of the {@code target} and resulting adapter.
+     * {@code V}/{@code v} stand for the return type and value of the
+     * {@code filter}, which are also found in the signature and arguments of
+     * the {@code target}, respectively, unless {@code V} is {@code void}.
+     * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types
+     * and values preceding and following the collection position, {@code pos},
+     * in the {@code target}'s signature. They also turn up in the resulting
+     * adapter's signature and arguments, where they surround
+     * {@code B}/{@code b}, which represent the parameter types and arguments
+     * to the {@code filter} (if any).
      * <blockquote><pre>{@code
      * T target(A...,V,C...);
      * V filter(B...);
@@ -2771,7 +2798,7 @@
      * // and if the filter has a void return:
      * T target3(A...,C...);
      * void filter3(B...);
-     * void adapter3(A... a,B... b,C... c) {
+     * T adapter3(A... a,B... b,C... c) {
      *   filter3(b...);
      *   return target3(a...,c...);
      * }
@@ -2791,6 +2818,9 @@
      * a non-void result, then {@code collectArguments(mh, N, coll)}
      * is equivalent to {@code filterArguments(mh, N, coll)}.
      * Other equivalences are possible but would require argument permutation.
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      *
      * @param target the method handle to invoke after filtering the subsequence of arguments
      * @param pos the position of the first adapter argument to pass to the filter,
@@ -2864,29 +2894,36 @@
 MethodHandle f0 = filterReturnValue(cat, length);
 System.out.println((int) f0.invokeExact("x", "y")); // 2
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code,
+     * {@code T}/{@code t} represent the result type and value of the
+     * {@code target}; {@code V}, the result type of the {@code filter}; and
+     * {@code A}/{@code a}, the types and values of the parameters and arguments
+     * of the {@code target} as well as the resulting adapter.
      * <blockquote><pre>{@code
-     * V target(A...);
-     * T filter(V);
-     * T adapter(A... a) {
-     *   V v = target(a...);
-     *   return filter(v);
+     * T target(A...);
+     * V filter(T);
+     * V adapter(A... a) {
+     *   T t = target(a...);
+     *   return filter(t);
      * }
      * // and if the target has a void return:
      * void target2(A...);
-     * T filter2();
-     * T adapter2(A... a) {
+     * V filter2();
+     * V adapter2(A... a) {
      *   target2(a...);
      *   return filter2();
      * }
      * // and if the filter has a void return:
-     * V target3(A...);
+     * T target3(A...);
      * void filter3(V);
      * void adapter3(A... a) {
-     *   V v = target3(a...);
-     *   filter3(v);
+     *   T t = target3(a...);
+     *   filter3(t);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param target the method handle to invoke before filtering the return value
      * @param filter method handle to call on the return value
      * @return method handle which incorporates the specified return value filtering logic
@@ -2964,7 +3001,15 @@
 // also prints "boo":
 assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the result type of the {@code target} and resulting adapter.
+     * {@code V}/{@code v} represent the type and value of the parameter and argument
+     * of {@code target} that precedes the folding position; {@code V} also is
+     * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+     * types and values of the {@code N} parameters and arguments at the folding
+     * position. {@code B}/{@code b} represent the types and values of the
+     * {@code target} parameters and arguments that follow the folded parameters
+     * and arguments.
      * <blockquote><pre>{@code
      * // there are N arguments in A...
      * T target(V, A[N]..., B...);
@@ -2981,6 +3026,9 @@
      *   return target2(a..., b...);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      * @param target the method handle to invoke after arguments are combined
      * @param combiner method handle to call initially on the incoming arguments
      * @return method handle which incorporates the specified argument folding logic
@@ -3022,7 +3070,13 @@
      * argument and return types, except that the return type
      * of the test must be boolean, and the test is allowed
      * to have fewer arguments than the other two method handles.
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>
+     * Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the uniform result type of the three involved handles;
+     * {@code A}/{@code a}, the types and values of the {@code target}
+     * parameters and arguments that are consumed by the {@code test}; and
+     * {@code B}/{@code b}, those types and values of the {@code target}
+     * parameters and arguments that are not consumed by the {@code test}.
      * <blockquote><pre>{@code
      * boolean test(A...);
      * T target(A...,B...);
@@ -3084,7 +3138,13 @@
      * argument and return types, except that handler may omit trailing arguments
      * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
      * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>
+     * Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the return type of the {@code target} and {@code handler},
+     * and correspondingly that of the resulting adapter; {@code A}/{@code a},
+     * the types and values of arguments to the resulting handle consumed by
+     * {@code handler}; and {@code B}/{@code b}, those of arguments to the
+     * resulting handle discarded by {@code handler}.
      * <blockquote><pre>{@code
      * T target(A..., B...);
      * T handler(ExType, A...);
@@ -3828,8 +3888,9 @@
      * (Note that, except for argument type conversions, combinators represent {@code void} values in parameter lists
      * by omitting the corresponding paradoxical arguments, not by inserting {@code null} or zero values.)
      * <p>
-     * The {@code target} and {@code cleanup} handles' return types must be the same. Their parameter type lists also
-     * must be the same, but the {@code cleanup} handle must accept one or two more leading parameters:<ul>
+     * The {@code target} and {@code cleanup} handles must have the same corresponding argument and return types, except
+     * that the {@code cleanup} handle may omit trailing arguments. Also, the {@code cleanup} handle must have one or
+     * two extra leading parameters:<ul>
      * <li>a {@code Throwable}, which will carry the exception thrown by the {@code target} handle (if any); and
      * <li>a parameter of the same type as the return type of both {@code target} and {@code cleanup}, which will carry
      * the result from the execution of the {@code target} handle.
@@ -3932,7 +3993,16 @@
     // also prints "jum":
     assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
      * }</pre></blockquote>
-     * <p> Here is pseudocode for the resulting adapter:
+     * <p>Here is pseudocode for the resulting adapter. In the code, {@code T}
+     * represents the result type of the {@code target} and resulting adapter.
+     * {@code V}/{@code v} represent the type and value of the parameter and argument
+     * of {@code target} that precedes the folding position; {@code V} also is
+     * the result type of the {@code combiner}. {@code A}/{@code a} denote the
+     * types and values of the {@code N} parameters and arguments at the folding
+     * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types
+     * and values of the {@code target} parameters and arguments that precede and
+     * follow the folded parameters and arguments starting at {@code pos},
+     * respectively.
      * <blockquote><pre>{@code
      * // there are N arguments in A...
      * T target(Z..., V, A[N]..., B...);
@@ -3949,6 +4019,9 @@
      *   return target2(z..., a..., b...);
      * }
      * }</pre></blockquote>
+     * <p>
+     * <em>Note:</em> The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector
+     * variable-arity method handle}, even if the original target method handle was.
      *
      * @param target the method handle to invoke after arguments are combined
      * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code
--- a/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/net/DatagramSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/DatagramSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/net/JarURLConnection.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/JarURLConnection.java	Thu Feb 25 11:27:30 2016 -0800
@@ -173,6 +173,14 @@
         }
 
         jarFileURL = new URL(spec.substring(0, separator++));
+        /*
+         * The url argument may have had a runtime fragment appended, so
+         * we need to add a runtime fragment to the jarFileURL to enable
+         * runtime versioning when the underlying jar file is opened.
+         */
+        if ("runtime".equals(url.getRef())) {
+            jarFileURL = new URL(jarFileURL, "#runtime");
+        }
         entryName = null;
 
         /* if ! is the last letter of the innerURL, entryName is null */
--- a/src/java.base/share/classes/java/net/MulticastSocket.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/MulticastSocket.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/net/SocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/SocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/net/SocketOptions.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/SocketOptions.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/net/StandardSocketOptions.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/net/StandardSocketOptions.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/java/nio/Bits.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/nio/Bits.java	Thu Feb 25 11:27:30 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);
     }
 
-    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 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);
+    }
 
-    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 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 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 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);
+    }
+
+    /**
+     * 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);
+    }
+
+    /**
+     * 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/src/java.base/share/classes/java/util/Currency.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/util/Currency.java	Thu Feb 25 11:27:30 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
@@ -92,7 +92,12 @@
  * and the remainder of entries in file are processed. For instances where duplicate
  * country code entries exist, the behavior of the Currency information for that
  * {@code Currency} is undefined and the remainder of entries in file are processed.
+ * <p>
+ * It is recommended to use {@link java.math.BigDecimal} class while dealing
+ * with {@code Currency} or monetary values as it provides better handling of floating
+ * point numbers and their operations.
  *
+ * @see java.math.BigDecimal
  * @since 1.4
  */
 public final class Currency implements Serializable {
@@ -516,14 +521,16 @@
     }
 
     /**
-     * Gets the default number of fraction digits used with this currency.
-     * For example, the default number of fraction digits for the Euro is 2,
-     * while for the Japanese Yen it's 0.
-     * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
-     * -1 is returned.
-     *
-     * @return the default number of fraction digits used with this currency
-     */
+    * Gets the default number of fraction digits used with this currency.
+    * Note that the number of fraction digits is the same as ISO 4217's
+    * minor unit for the currency.
+    * For example, the default number of fraction digits for the Euro is 2,
+    * while for the Japanese Yen it's 0.
+    * In the case of pseudo-currencies, such as IMF Special Drawing Rights,
+    * -1 is returned.
+    *
+    * @return the default number of fraction digits used with this currency
+    */
     public int getDefaultFractionDigits() {
         return defaultFractionDigits;
     }
--- a/src/java.base/share/classes/java/util/jar/Attributes.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/util/jar/Attributes.java	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2015, 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
@@ -646,5 +646,13 @@
          * manifest attribute used for package versioning.
          */
         public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor");
+
+        /**
+         * {@code Name} object for {@code Multi-Release}
+         * manifest attribute that indicates this is a multi-release JAR file.
+         *
+         * @since   9
+         */
+        public static final Name MULTI_RELEASE = new Name("Multi-Release");
     }
 }
--- a/src/java.base/share/classes/java/util/jar/JarFile.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/java/util/jar/JarFile.java	Thu Feb 25 11:27:30 2016 -0800
@@ -28,6 +28,7 @@
 import java.io.*;
 import java.lang.ref.SoftReference;
 import java.net.URL;
+import java.security.PrivilegedAction;
 import java.util.*;
 import java.util.stream.Stream;
 import java.util.stream.StreamSupport;
@@ -37,28 +38,91 @@
 import java.security.AccessController;
 import java.security.CodeSource;
 import jdk.internal.misc.SharedSecrets;
-import sun.security.action.GetPropertyAction;
 import sun.security.util.ManifestEntryVerifier;
 import sun.security.util.SignatureFileVerifier;
 
+import static java.util.jar.Attributes.Name.MULTI_RELEASE;
+
 /**
  * The {@code JarFile} class is used to read the contents of a jar file
  * from any file that can be opened with {@code java.io.RandomAccessFile}.
  * It extends the class {@code java.util.zip.ZipFile} with support
- * for reading an optional {@code Manifest} entry. The
- * {@code Manifest} can be used to specify meta-information about the
- * jar file and its entries.
+ * for reading an optional {@code Manifest} entry, and support for
+ * processing multi-release jar files.  The {@code Manifest} can be used
+ * to specify meta-information about the jar file and its entries.
+ *
+ * <p>A multi-release jar file is a jar file that contains
+ * a manifest with a main attribute named "Multi-Release",
+ * a set of "base" entries, some of which are public classes with public
+ * or protected methods that comprise the public interface of the jar file,
+ * and a set of "versioned" entries contained in subdirectories of the
+ * "META-INF/versions" directory.  The versioned entries are partitioned by the
+ * major version of the Java platform.  A versioned entry, with a version
+ * {@code n}, {@code 8 < n}, in the "META-INF/versions/{n}" directory overrides
+ * the base entry as well as any entry with a version number {@code i} where
+ * {@code 8 < i < n}.
+ *
+ * <p>By default, a {@code JarFile} for a multi-release jar file is configured
+ * to process the multi-release jar file as if it were a plain (unversioned) jar
+ * file, and as such an entry name is associated with at most one base entry.
+ * The {@code JarFile} may be configured to process a multi-release jar file by
+ * creating the {@code JarFile} with the
+ * {@link JarFile#JarFile(File, boolean, int, Release)} constructor.  The
+ * {@code Release} object sets a maximum version used when searching for
+ * versioned entries.  When so configured, an entry name
+ * can correspond with at most one base entry and zero or more versioned
+ * entries. A search is required to associate the entry name with the latest
+ * versioned entry whose version is less than or equal to the maximum version
+ * (see {@link #getEntry(String)}).
+ *
+ * <p>Class loaders that utilize {@code JarFile} to load classes from the
+ * contents of {@code JarFile} entries should construct the {@code JarFile}
+ * by invoking the {@link JarFile#JarFile(File, boolean, int, Release)}
+ * constructor with the value {@code Release.RUNTIME} assigned to the last
+ * argument.  This assures that classes compatible with the major
+ * version of the running JVM are loaded from multi-release jar files.
+ *
+ * <p>If the verify flag is on when opening a signed jar file, the content of
+ * the file is verified against its signature embedded inside the file. Please
+ * note that the verification process does not include validating the signer's
+ * certificate. A caller should inspect the return value of
+ * {@link JarEntry#getCodeSigners()} to further determine if the signature
+ * can be trusted.
  *
  * <p> Unless otherwise noted, passing a {@code null} argument to a constructor
  * or method in this class will cause a {@link NullPointerException} to be
  * thrown.
  *
- * If the verify flag is on when opening a signed jar file, the content of the
- * file is verified against its signature embedded inside the file. Please note
- * that the verification process does not include validating the signer's
- * certificate. A caller should inspect the return value of
- * {@link JarEntry#getCodeSigners()} to further determine if the signature
- * can be trusted.
+ * @implNote
+ * <div class="block">
+ * If the API can not be used to configure a {@code JarFile} (e.g. to override
+ * the configuration of a compiled application or library), two {@code System}
+ * properties are available.
+ * <ul>
+ * <li>
+ * {@code jdk.util.jar.version} can be assigned a value that is the
+ * {@code String} representation of a non-negative integer
+ * {@code <= Version.current().major()}.  The value is used to set the effective
+ * runtime version to something other than the default value obtained by
+ * evaluating {@code Version.current().major()}. The effective runtime version
+ * is the version that the {@link JarFile#JarFile(File, boolean, int, Release)}
+ * constructor uses when the value of the last argument is
+ * {@code Release.RUNTIME}.
+ * </li>
+ * <li>
+ * {@code jdk.util.jar.enableMultiRelease} can be assigned one of the three
+ * {@code String} values <em>true</em>, <em>false</em>, or <em>force</em>.  The
+ * value <em>true</em>, the default value, enables multi-release jar file
+ * processing.  The value <em>false</em> disables multi-release jar processing,
+ * ignoring the "Multi-Release" manifest attribute, and the versioned
+ * directories in a multi-release jar file if they exist.  Furthermore,
+ * the method {@link JarFile#isMultiRelease()} returns <em>false</em>. The value
+ * <em>force</em> causes the {@code JarFile} to be initialized to runtime
+ * versioning after construction.  It effectively does the same as this code:
+ * {@code (new JarFile(File, boolean, int, Release.RUNTIME)}.
+ * </li>
+ * </ul>
+ * </div>
  *
  * @author  David Connelly
  * @see     Manifest
@@ -68,26 +132,126 @@
  */
 public
 class JarFile extends ZipFile {
+    private final static int BASE_VERSION;
+    private final static int RUNTIME_VERSION;
+    private final static boolean MULTI_RELEASE_ENABLED;
+    private final static boolean MULTI_RELEASE_FORCED;
     private SoftReference<Manifest> manRef;
     private JarEntry manEntry;
     private JarVerifier jv;
     private boolean jvInitialized;
     private boolean verify;
+    private final int version;
+    private boolean notVersioned;
+    private final boolean runtimeVersioned;
 
     // indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true)
     private boolean hasClassPathAttribute;
     // true if manifest checked for special attributes
     private volatile boolean hasCheckedSpecialAttributes;
 
-    // Set up JavaUtilJarAccess in SharedSecrets
     static {
+        // Set up JavaUtilJarAccess in SharedSecrets
         SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl());
+
+        BASE_VERSION = 8;  // one less than lowest version for versioned entries
+        RUNTIME_VERSION = AccessController.doPrivileged(
+                new PrivilegedAction<Integer>() {
+                    public Integer run() {
+                        Integer v = sun.misc.Version.jdkMajorVersion(); // fixme when JEP 223 Version integrated
+                        Integer i = Integer.getInteger("jdk.util.jar.version", v);
+                        i = i < 0 ? 0 : i;
+                        return i > v ? v : i;
+                    }
+                }
+        );
+        String multi_release = AccessController.doPrivileged(
+                new PrivilegedAction<String>() {
+                    public String run() {
+                        return System.getProperty("jdk.util.jar.enableMultiRelease", "true");
+                    }
+                }
+        );
+        switch (multi_release) {
+            case "true":
+            default:
+                MULTI_RELEASE_ENABLED = true;
+                MULTI_RELEASE_FORCED = false;
+                break;
+            case "false":
+                MULTI_RELEASE_ENABLED = false;
+                MULTI_RELEASE_FORCED = false;
+                break;
+            case "force":
+                MULTI_RELEASE_ENABLED = true;
+                MULTI_RELEASE_FORCED = true;
+                break;
+        }
     }
 
     /**
+     * A set of constants that represent the entries in either the base directory
+     * or one of the versioned directories in a multi-release jar file.  It's
+     * possible for a multi-release jar file to contain versioned directories
+     * that are not represented by the constants of the {@code Release} enum.
+     * In those cases, the entries will not be located by this {@code JarFile}
+     * through the aliasing mechanism, but they can be directly accessed by
+     * specifying the full path name of the entry.
+     *
+     * @since 9
+     */
+    public enum Release {
+        /**
+         * Represents unversioned entries, or entries in "regular", as opposed
+         * to multi-release jar files.
+         */
+        BASE(BASE_VERSION),
+
+        /**
+         * Represents entries found in the META-INF/versions/9 directory of a
+         * multi-release jar file.
+         */
+        VERSION_9(9),
+
+        // fill in the "blanks" for future releases
+
+        /**
+         * Represents entries found in the META-INF/versions/{n} directory of a
+         * multi-release jar file, where {@code n} is the effective runtime
+         * version of the jar file.
+         *
+         * @implNote
+         * <div class="block">
+         * The effective runtime version is determined
+         * by evaluating {@code Version.current().major()} or by using the value
+         * of the {@code jdk.util.jar.version} System property if it exists.
+         * </div>
+         */
+        RUNTIME(RUNTIME_VERSION);
+
+        Release(int version) {
+            this.version = version;
+        }
+
+        private static Release valueOf(int version) {
+            return version <= BASE.value() ? BASE : valueOf("VERSION_" + version);
+        }
+
+        private final int version;
+
+        private int value() {
+            return this.version;
+        }
+    }
+
+    private static final String META_INF = "META-INF/";
+
+    private static final String META_INF_VERSIONS = META_INF + "versions/";
+
+    /**
      * The JAR manifest file name.
      */
-    public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF";
+    public static final String MANIFEST_NAME = META_INF + "MANIFEST.MF";
 
     /**
      * Creates a new {@code JarFile} to read from the specified
@@ -129,7 +293,6 @@
         this(file, true, ZipFile.OPEN_READ);
     }
 
-
     /**
      * Creates a new {@code JarFile} to read from the specified
      * {@code File} object.
@@ -144,7 +307,6 @@
         this(file, verify, ZipFile.OPEN_READ);
     }
 
-
     /**
      * Creates a new {@code JarFile} to read from the specified
      * {@code File} object in the specified mode.  The mode argument
@@ -162,10 +324,104 @@
      * @since 1.3
      */
     public JarFile(File file, boolean verify, int mode) throws IOException {
+        this(file, verify, mode, Release.BASE);
+        this.notVersioned = true;
+    }
+
+    /**
+     * Creates a new {@code JarFile} to read from the specified
+     * {@code File} object in the specified mode.  The mode argument
+     * must be either {@code OPEN_READ} or {@code OPEN_READ | OPEN_DELETE}.
+     * The version argument configures the {@code JarFile} for processing
+     * multi-release jar files.
+     *
+     * @param file the jar file to be opened for reading
+     * @param verify whether or not to verify the jar file if
+     * it is signed.
+     * @param mode the mode in which the file is to be opened
+     * @param version specifies the release version for a multi-release jar file
+     * @throws IOException if an I/O error has occurred
+     * @throws IllegalArgumentException
+     *         if the {@code mode} argument is invalid
+     * @throws SecurityException if access to the file is denied
+     *         by the SecurityManager
+     * @throws NullPointerException if {@code version} is {@code null}
+     * @since 9
+     */
+    public JarFile(File file, boolean verify, int mode, Release version) throws IOException {
         super(file, mode);
+        Objects.requireNonNull(version);
         this.verify = verify;
+        // version applies to multi-release jar files, ignored for regular jar files
+        this.version = MULTI_RELEASE_FORCED ? RUNTIME_VERSION : version.value();
+        this.runtimeVersioned = version == Release.RUNTIME;
+        assert runtimeVersionExists();
     }
 
+    private boolean runtimeVersionExists() {
+        int version = sun.misc.Version.jdkMajorVersion();  // fixme when JEP 223 integrated
+        try {
+            Release.valueOf(version);
+            return true;
+        } catch (IllegalArgumentException x) {
+            System.err.println("No JarFile.Release object for release " + version);
+            return false;
+        }
+    }
+
+    /**
+     * Returns the maximum version used when searching for versioned entries.
+     *
+     * @return the maximum version, or {@code Release.BASE} if this jar file is
+     *         processed as if it is an unversioned jar file or is not a
+     *         multi-release jar file
+     * @since 9
+     */
+    public final Release getVersion() {
+        if (isMultiRelease()) {
+            return runtimeVersioned ? Release.RUNTIME : Release.valueOf(version);
+        } else {
+            return Release.BASE;
+        }
+    }
+
+    /**
+     * Indicates whether or not this jar file is a multi-release jar file.
+     *
+     * @return true if this JarFile is a multi-release jar file
+     * @since 9
+     */
+    public final boolean isMultiRelease() {
+        // do not call this code in a constructor because some subclasses use
+        // lazy loading of manifest so it won't be available at construction time
+        if (MULTI_RELEASE_ENABLED) {
+            // Doubled-checked locking pattern
+            Boolean result = isMultiRelease;
+            if (result == null) {
+                synchronized (this) {
+                    result = isMultiRelease;
+                    if (result == null) {
+                        Manifest man = null;
+                        try {
+                            man = getManifest();
+                        } catch (IOException e) {
+                            //Ignored, manifest cannot be read
+                        }
+                        isMultiRelease = result = (man != null)
+                                && man.getMainAttributes().containsKey(MULTI_RELEASE)
+                                ? Boolean.TRUE : Boolean.FALSE;
+                    }
+                }
+            }
+            return result == Boolean.TRUE;
+        } else {
+            return false;
+        }
+    }
+    // the following field, isMultiRelease, should only be used in the method
+    // isMultiRelease(), like a static local
+    private volatile Boolean isMultiRelease;    // is jar multi-release?
+
     /**
      * Returns the jar file manifest, or {@code null} if none.
      *
@@ -209,40 +465,87 @@
     }
 
     /**
-     * Returns the {@code JarEntry} for the given entry name or
+     * Returns the {@code JarEntry} for the given base entry name or
      * {@code null} if not found.
      *
+     * <p>If this {@code JarFile} is a multi-release jar file and is configured
+     * to be processed as such, then a search is performed to find and return
+     * a {@code JarEntry} that is the latest versioned entry associated with the
+     * given entry name.  The returned {@code JarEntry} is the versioned entry
+     * corresponding to the given base entry name prefixed with the string
+     * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for
+     * which an entry exists.  If such a versioned entry does not exist, then
+     * the {@code JarEntry} for the base entry is returned, otherwise
+     * {@code null} is returned if no entries are found.  The initial value for
+     * the version {@code n} is the maximum version as returned by the method
+     * {@link JarFile#getVersion()}.
+     *
      * @param name the jar file entry name
-     * @return the {@code JarEntry} for the given entry name or
-     *         {@code null} if not found.
+     * @return the {@code JarEntry} for the given entry name, or
+     *         the versioned entry name, or {@code null} if not found
      *
      * @throws IllegalStateException
      *         may be thrown if the jar file has been closed
      *
      * @see java.util.jar.JarEntry
+     *
+     * @implSpec
+     * <div class="block">
+     * This implementation invokes {@link JarFile#getEntry(String)}.
+     * </div>
      */
     public JarEntry getJarEntry(String name) {
         return (JarEntry)getEntry(name);
     }
 
     /**
-     * Returns the {@code ZipEntry} for the given entry name or
+     * Returns the {@code ZipEntry} for the given base entry name or
      * {@code null} if not found.
      *
+     * <p>If this {@code JarFile} is a multi-release jar file and is configured
+     * to be processed as such, then a search is performed to find and return
+     * a {@code ZipEntry} that is the latest versioned entry associated with the
+     * given entry name.  The returned {@code ZipEntry} is the versioned entry
+     * corresponding to the given base entry name prefixed with the string
+     * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for
+     * which an entry exists.  If such a versioned entry does not exist, then
+     * the {@code ZipEntry} for the base entry is returned, otherwise
+     * {@code null} is returned if no entries are found.  The initial value for
+     * the version {@code n} is the maximum version as returned by the method
+     * {@link JarFile#getVersion()}.
+     *
      * @param name the jar file entry name
      * @return the {@code ZipEntry} for the given entry name or
-     *         {@code null} if not found
+     *         the versioned entry name or {@code null} if not found
      *
      * @throws IllegalStateException
      *         may be thrown if the jar file has been closed
      *
      * @see java.util.zip.ZipEntry
+     *
+     * @implSpec
+     * <div class="block">
+     * This implementation may return a versioned entry for the requested name
+     * even if there is not a corresponding base entry.  This can occur
+     * if there is a private or package-private versioned entry that matches.
+     * If a subclass overrides this method, assure that the override method
+     * invokes {@code super.getEntry(name)} to obtain all versioned entries.
+     * </div>
      */
     public ZipEntry getEntry(String name) {
         ZipEntry ze = super.getEntry(name);
         if (ze != null) {
             return new JarFileEntry(ze);
         }
+        // no matching base entry, but maybe there is a versioned entry,
+        // like a new private class
+        if (isMultiRelease()) {
+            ze = new ZipEntry(name);
+            ZipEntry vze = getVersionedEntry(ze);
+            if (ze != vze) {
+                return new JarFileEntry(name, vze);
+            }
+        }
         return null;
     }
 
@@ -250,14 +553,42 @@
             Iterator<JarEntry>
     {
         final Enumeration<? extends ZipEntry> e = JarFile.super.entries();
+        ZipEntry ze;
 
         public boolean hasNext() {
-            return e.hasMoreElements();
+            if (notVersioned) {
+                return e.hasMoreElements();
+            }
+            if (ze != null) {
+                return true;
+            }
+            return findNext();
+        }
+
+        private boolean findNext() {
+            while (e.hasMoreElements()) {
+                ZipEntry ze2 = e.nextElement();
+                if (!ze2.getName().startsWith(META_INF_VERSIONS)) {
+                    ze = ze2;
+                    return true;
+                }
+            }
+            return false;
         }
 
         public JarEntry next() {
-            ZipEntry ze = e.nextElement();
-            return new JarFileEntry(ze);
+            ZipEntry ze2;
+
+            if (notVersioned) {
+                ze2 = e.nextElement();
+                return new JarFileEntry(ze2.getName(), ze2);
+            }
+            if (ze != null || findNext()) {
+                ze2 = ze;
+                ze = null;
+                return new JarFileEntry(ze2);
+            }
+            throw new NoSuchElementException();
         }
 
         public boolean hasMoreElements() {
@@ -274,7 +605,19 @@
     }
 
     /**
-     * Returns an enumeration of the jar file entries.
+     * Returns an enumeration of the jar file entries.  The set of entries
+     * returned depends on whether or not the jar file is a multi-release jar
+     * file, and on the constructor used to create the {@code JarFile}.  If the
+     * jar file is not a multi-release jar file, all entries are returned,
+     * regardless of how the {@code JarFile} is created.  If the constructor
+     * does not take a {@code Release} argument, all entries are returned.
+     * If the jar file is a multi-release jar file and the constructor takes a
+     * {@code Release} argument, then the set of entries returned is equivalent
+     * to the set of entries that would be returned if the set was built by
+     * invoking {@link JarFile#getEntry(String)} or
+     * {@link JarFile#getJarEntry(String)} with the name of each base entry in
+     * the jar file.  A base entry is an entry whose path name does not start
+     * with "META-INF/versions/".
      *
      * @return an enumeration of the jar file entries
      * @throws IllegalStateException
@@ -285,10 +628,21 @@
     }
 
     /**
-     * Returns an ordered {@code Stream} over the jar file entries.
+     * Returns an ordered {@code Stream} over all the jar file entries.
      * Entries appear in the {@code Stream} in the order they appear in
-     * the central directory of the jar file.
-     *
+     * the central directory of the jar file.  The set of entries
+     * returned depends on whether or not the jar file is a multi-release jar
+     * file, and on the constructor used to create the {@code JarFile}.  If the
+     * jar file is not a multi-release jar file, all entries are returned,
+     * regardless of how the {@code JarFile} is created.  If the constructor
+     * does not take a {@code Release} argument, all entries are returned.
+     * If the jar file is a multi-release jar file and the constructor takes a
+     * {@code Release} argument, then the set of entries returned is equivalent
+     * to the set of entries that would be returned if the set was built by
+     * invoking {@link JarFile#getEntry(String)} or
+     * {@link JarFile#getJarEntry(String)} with the name of each base entry in
+     * the jar file.  A base entry is an entry whose path name does not start
+     * with "META-INF/versions/".
      * @return an ordered {@code Stream} of entries in this jar file
      * @throws IllegalStateException if the jar file has been closed
      * @since 1.8
@@ -300,14 +654,44 @@
                         Spliterator.IMMUTABLE | Spliterator.NONNULL), false);
     }
 
+    private ZipEntry searchForVersionedEntry(final int version, String name) {
+        ZipEntry vze = null;
+        String sname = "/" + name;
+        int i = version;
+        while (i > BASE_VERSION) {
+            vze = super.getEntry(META_INF_VERSIONS + i + sname);
+            if (vze != null) break;
+            i--;
+        }
+        return vze;
+    }
+
+    private ZipEntry getVersionedEntry(ZipEntry ze) {
+        ZipEntry vze = null;
+        if (version > BASE_VERSION && !ze.isDirectory()) {
+            String name = ze.getName();
+            if (!name.startsWith(META_INF)) {
+                vze = searchForVersionedEntry(version, name);
+            }
+        }
+        return vze == null ? ze : vze;
+    }
+
     private class JarFileEntry extends JarEntry {
+        final private String name;
+
         JarFileEntry(ZipEntry ze) {
-            super(ze);
+            super(isMultiRelease() ? getVersionedEntry(ze) : ze);
+            this.name = ze.getName();
+        }
+        JarFileEntry(String name, ZipEntry vze) {
+            super(vze);
+            this.name = name;
         }
         public Attributes getAttributes() throws IOException {
             Manifest man = JarFile.this.getManifest();
             if (man != null) {
-                return man.getAttributes(getName());
+                return man.getAttributes(super.getName());
             } else {
                 return null;
             }
@@ -319,7 +703,7 @@
                 throw new RuntimeException(e);
             }
             if (certs == null && jv != null) {
-                certs = jv.getCerts(JarFile.this, this);
+                certs = jv.getCerts(JarFile.this, reifiedEntry());
             }
             return certs == null ? null : certs.clone();
         }
@@ -330,10 +714,22 @@
                 throw new RuntimeException(e);
             }
             if (signers == null && jv != null) {
-                signers = jv.getCodeSigners(JarFile.this, this);
+                signers = jv.getCodeSigners(JarFile.this, reifiedEntry());
             }
             return signers == null ? null : signers.clone();
         }
+        JarFileEntry reifiedEntry() {
+            if (isMultiRelease()) {
+                String entryName = super.getName();
+                return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this);
+            }
+            return this;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
     }
 
     /*
@@ -491,12 +887,19 @@
         // wrap a verifier stream around the real stream
         return new JarVerifier.VerifierStream(
             getManifestFromReference(),
-            ze instanceof JarFileEntry ?
-            (JarEntry) ze : getJarEntry(ze.getName()),
+            verifiableEntry(ze),
             super.getInputStream(ze),
             jv);
     }
 
+    private JarEntry verifiableEntry(ZipEntry ze) {
+        if (!(ze instanceof JarFileEntry)) {
+            ze = getJarEntry(ze.getName());
+        }
+        // assure the name and entry match for verification
+        return ze == null ? null : ((JarFileEntry)ze).reifiedEntry();
+    }
+
     // Statics for hand-coded Boyer-Moore search
     private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'};
     // The bad character shift for "class-path"
@@ -523,7 +926,7 @@
     private JarEntry getManEntry() {
         if (manEntry == null) {
             // First look up manifest entry using standard name
-            manEntry = getJarEntry(MANIFEST_NAME);
+            ZipEntry manEntry = super.getEntry(MANIFEST_NAME);
             if (manEntry == null) {
                 // If not found, then iterate through all the "META-INF/"
                 // entries to find a match.
@@ -531,12 +934,15 @@
                 if (names != null) {
                     for (String name : names) {
                         if (MANIFEST_NAME.equals(name.toUpperCase(Locale.ENGLISH))) {
-                            manEntry = getJarEntry(name);
+                            manEntry = super.getEntry(name);
                             break;
                         }
                     }
                 }
             }
+            this.manEntry = (manEntry == null)
+                    ? null
+                    : new JarFileEntry(manEntry.getName(), manEntry);
         }
         return manEntry;
     }
--- a/src/java.base/share/classes/javax/crypto/JceSecurity.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/javax/crypto/JceSecurity.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/jdk/internal/misc/Signal.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/jdk/internal/misc/Signal.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/jdk/internal/misc/Unsafe.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/jdk/net/Sockets.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/jdk/net/Sockets.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/sun/misc/URLClassPath.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/misc/URLClassPath.java	Thu Feb 25 11:27:30 2016 -0800
@@ -63,6 +63,7 @@
 import java.util.jar.Manifest;
 import java.util.jar.Attributes;
 import java.util.jar.Attributes.Name;
+import java.util.zip.ZipFile;
 
 import jdk.internal.jimage.ImageLocation;
 import jdk.internal.jimage.ImageReader;
@@ -727,9 +728,10 @@
                 if (!p.exists()) {
                     throw new FileNotFoundException(p.getPath());
                 }
-                return checkJar(new JarFile(p.getPath()));
+                return checkJar(new JarFile(new File(p.getPath()), true, ZipFile.OPEN_READ,
+                        JarFile.Release.RUNTIME));
             }
-            URLConnection uc = getBaseURL().openConnection();
+            URLConnection uc = (new URL(getBaseURL(), "#runtime")).openConnection();
             uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION);
             JarFile jarFile = ((JarURLConnection)uc).getJarFile();
             return checkJar(jarFile);
@@ -756,7 +758,9 @@
 
             final URL url;
             try {
-                url = new URL(getBaseURL(), ParseUtil.encodePath(name, false));
+                // add #runtime fragment to tell JarURLConnection to use
+                // runtime versioning if the underlying jar file is multi-release
+                url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime");
                 if (check) {
                     URLClassPath.check(url);
                 }
--- a/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java	Thu Feb 25 11:27:30 2016 -0800
@@ -65,9 +65,10 @@
     }
 
     static JarFile getJarFile(URL url, URLJarFileCloseController closeController) throws IOException {
-        if (isFileURL(url))
-            return new URLJarFile(url, closeController);
-        else {
+        if (isFileURL(url)) {
+            Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE;
+            return new URLJarFile(url, closeController, version);
+        } else {
             return retrieve(url, closeController);
         }
     }
@@ -89,8 +90,13 @@
         this.closeController = closeController;
     }
 
-    private URLJarFile(URL url, URLJarFileCloseController closeController) throws IOException {
-        super(ParseUtil.decode(url.getFile()));
+    private URLJarFile(File file, URLJarFileCloseController closeController, Release version) throws IOException {
+        super(file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE, version);
+        this.closeController = closeController;
+    }
+
+    private URLJarFile(URL url, URLJarFileCloseController closeController, Release version) throws IOException {
+        super(new File(ParseUtil.decode(url.getFile())), true, ZipFile.OPEN_READ, version);
         this.closeController = closeController;
     }
 
@@ -179,14 +185,6 @@
      * Given a URL, retrieves a JAR file, caches it to disk, and creates a
      * cached JAR file object.
      */
-    private static JarFile retrieve(final URL url) throws IOException {
-        return retrieve(url, null);
-    }
-
-    /**
-     * Given a URL, retrieves a JAR file, caches it to disk, and creates a
-     * cached JAR file object.
-     */
      private static JarFile retrieve(final URL url, final URLJarFileCloseController closeController) throws IOException {
         /*
          * See if interface is set, then call retrieve function of the class
@@ -202,6 +200,7 @@
         {
 
             JarFile result = null;
+            Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE;
 
             /* get the stream before asserting privileges */
             try (final InputStream in = url.openConnection().getInputStream()) {
@@ -211,7 +210,7 @@
                             Path tmpFile = Files.createTempFile("jar_cache", null);
                             try {
                                 Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING);
-                                JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController);
+                                JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController, version);
                                 tmpFile.toFile().deleteOnExit();
                                 return jarFile;
                             } catch (Throwable thr) {
--- a/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/sun/nio/ch/Net.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/nio/ch/Net.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java	Thu Feb 25 11:27:30 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/src/java.base/share/native/libjava/Bits.c	Thu Feb 25 09:41:46 2016 -0800
+++ /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/src/java.base/share/native/libnet/net_util.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/native/libnet/net_util.c	Thu Feb 25 11:27:30 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/src/java.base/share/native/libnet/net_util.h	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/native/libnet/net_util.h	Thu Feb 25 11:27:30 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/src/java.base/share/native/libzip/CRC32.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/share/native/libzip/CRC32.c	Thu Feb 25 11:27:30 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/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/classes/java/net/PlainSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java	Thu Feb 25 11:27:30 2016 -0800
@@ -85,7 +85,7 @@
                 synchronized (instance) {
                     result = getCachedJarFile(url);
                     if (result == null) {
-                        fileCache.put(URLUtil.urlNoFragString(url), local_result);
+                        fileCache.put(urlKey(url), local_result);
                         urlCache.put(local_result, url);
                         result = local_result;
                     } else {
@@ -113,13 +113,13 @@
         synchronized (instance) {
             URL urlRemoved = urlCache.remove(jarFile);
             if (urlRemoved != null)
-                fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
+                fileCache.remove(urlKey(urlRemoved));
         }
     }
 
     private JarFile getCachedJarFile(URL url) {
         assert Thread.holdsLock(instance);
-        JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
+        JarFile result = fileCache.get(urlKey(url));
 
         /* if the JAR file is cached, the permission will always be there */
         if (result != null) {
@@ -149,6 +149,12 @@
         return result;
     }
 
+    private String urlKey(URL url) {
+        String urlstr =  URLUtil.urlNoFragString(url);
+        if ("runtime".equals(url.getRef())) urlstr += "#runtime";
+        return urlstr;
+    }
+
     private Permission getPermission(JarFile jarFile) {
         try {
             URLConnection uc = getConnection(jarFile);
--- a/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c	Thu Feb 25 11:27:30 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/src/java.base/unix/native/libnet/SdpSupport.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/native/libnet/SdpSupport.c	Thu Feb 25 11:27:30 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/src/java.base/unix/native/libnet/SocketImpl.c	Thu Feb 25 11:27:30 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/src/java.base/unix/native/libnet/net_util_md.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/native/libnet/net_util_md.c	Thu Feb 25 11:27:30 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/src/java.base/unix/native/libnet/net_util_md.h	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/native/libnet/net_util_md.h	Thu Feb 25 11:27:30 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/src/java.base/unix/native/libnio/ch/Net.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/native/libnio/ch/Net.c	Thu Feb 25 11:27:30 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/src/java.base/unix/native/libnio/ch/nio_util.h	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/unix/native/libnio/ch/nio_util.h	Thu Feb 25 11:27:30 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/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java	Thu Feb 25 11:27:30 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/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java	Thu Feb 25 11:27:30 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);
     }
--- a/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java	Thu Feb 25 11:27:30 2016 -0800
@@ -95,7 +95,7 @@
                 synchronized (instance) {
                     result = getCachedJarFile(url);
                     if (result == null) {
-                        fileCache.put(URLUtil.urlNoFragString(url), local_result);
+                        fileCache.put(urlKey(url), local_result);
                         urlCache.put(local_result, url);
                         result = local_result;
                     } else {
@@ -123,13 +123,13 @@
         synchronized (instance) {
             URL urlRemoved = urlCache.remove(jarFile);
             if (urlRemoved != null)
-                fileCache.remove(URLUtil.urlNoFragString(urlRemoved));
+                fileCache.remove(urlKey(urlRemoved));
         }
     }
 
     private JarFile getCachedJarFile(URL url) {
         assert Thread.holdsLock(instance);
-        JarFile result = fileCache.get(URLUtil.urlNoFragString(url));
+        JarFile result = fileCache.get(urlKey(url));
 
         /* if the JAR file is cached, the permission will always be there */
         if (result != null) {
@@ -159,6 +159,12 @@
         return result;
     }
 
+    private String urlKey(URL url) {
+        String urlstr =  URLUtil.urlNoFragString(url);
+        if ("runtime".equals(url.getRef())) urlstr += "#runtime";
+        return urlstr;
+    }
+
     private Permission getPermission(JarFile jarFile) {
         try {
             URLConnection uc = getConnection(jarFile);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/windows/native/libnet/SocketImpl.c	Thu Feb 25 11:27:30 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/src/java.base/windows/native/libnet/net_util_md.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/native/libnet/net_util_md.c	Thu Feb 25 11:27:30 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/src/java.base/windows/native/libnet/net_util_md.h	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/native/libnet/net_util_md.h	Thu Feb 25 11:27:30 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/src/java.base/windows/native/libnio/ch/Net.c	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/java.base/windows/native/libnio/ch/Net.c	Thu Feb 25 11:27:30 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/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo	Thu Feb 25 09:41:46 2016 -0800
+++ b/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo	Thu Feb 25 11:27:30 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/test/java/net/SocketOption/OptionsTest.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/java/net/SocketOption/OptionsTest.java	Thu Feb 25 11:27:30 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/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java	Thu Feb 25 11:27:30 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/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/java/nio/channels/AsynchronousSocketChannel/Basic.java	Thu Feb 25 11:27:30 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/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/java/nio/channels/DatagramChannel/SocketOptionTests.java	Thu Feb 25 11:27:30 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/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java	Thu Feb 25 11:27:30 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 {
--- a/test/java/nio/file/Files/probeContentType/Basic.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/java/nio/file/Files/probeContentType/Basic.java	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, 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
@@ -29,8 +29,9 @@
  * @run main/othervm Basic
  */
 
+import java.io.*;
 import java.nio.file.*;
-import java.io.*;
+import java.util.stream.Stream;
 
 /**
  * Uses Files.probeContentType to probe html file, custom file type, and minimal
@@ -38,6 +39,9 @@
  */
 public class Basic {
 
+    private static final boolean IS_UNIX =
+        ! System.getProperty("os.name").startsWith("Windows");
+
     static Path createHtmlFile() throws IOException {
         Path file = Files.createTempFile("foo", ".html");
         try (OutputStream out = Files.newOutputStream(file)) {
@@ -51,10 +55,61 @@
         return Files.createTempFile("red", ".grape");
     }
 
-    static void checkContentTypes(String[] extensions, String[] expectedTypes)
+    private static int checkContentTypes(String expected, String actual) {
+        assert expected != null;
+        assert actual != null;
+
+        if (!expected.equals(actual)) {
+            if (IS_UNIX) {
+                Path userMimeTypes =
+                    Paths.get(System.getProperty("user.home"), ".mime.types");
+                if (!Files.exists(userMimeTypes)) {
+                    System.out.println(userMimeTypes + " does not exist");
+                } else if (!Files.isReadable(userMimeTypes)) {
+                    System.out.println(userMimeTypes + " is not readable");
+                } else {
+                    System.out.println(userMimeTypes + " contents:");
+                    try (Stream<String> lines = Files.lines(userMimeTypes)) {
+                        lines.forEach(System.out::println);
+                        System.out.println("");
+                    } catch (IOException ioe) {
+                        System.err.println("Problem reading "
+                                           + userMimeTypes);
+                    }
+                }
+
+                Path etcMimeTypes = Paths.get("/etc/mime.types");
+                if (!Files.exists(etcMimeTypes)) {
+                    System.out.println(etcMimeTypes + " does not exist");
+                } else if (!Files.isReadable(etcMimeTypes)) {
+                    System.out.println(etcMimeTypes + " is not readable");
+                } else {
+                    System.out.println(etcMimeTypes + " contents:");
+                    try (Stream<String> lines = Files.lines(etcMimeTypes)) {
+                        lines.forEach(System.out::println);
+                        System.out.println("");
+                    } catch (IOException ioe) {
+                        System.err.println("Problem reading "
+                                           + etcMimeTypes);
+                    }
+                }
+            }
+
+            System.err.println("Expected \"" + expected
+                               + "\" but obtained \""
+                               + actual + "\"");
+
+            return 1;
+        }
+
+        return 0;
+    }
+
+    static int checkOSXContentTypes(String[] extensions, String[] expectedTypes)
         throws IOException {
         if (extensions.length != expectedTypes.length) {
-            throw new IllegalArgumentException("Parameter array lengths differ");
+            throw new IllegalArgumentException
+                ("Parameter array lengths differ");
         }
 
         int failures = 0;
@@ -79,12 +134,11 @@
             }
         }
 
-        if (failures > 0) {
-            throw new RuntimeException("Test failed!");
-        }
+        return failures;
     }
 
     public static void main(String[] args) throws IOException {
+        int failures = 0;
 
         // exercise default file type detector
         Path file = createHtmlFile();
@@ -93,8 +147,7 @@
             if (type == null) {
                 System.err.println("Content type cannot be determined - test skipped");
             } else {
-                if (!type.equals("text/html"))
-                    throw new RuntimeException("Unexpected type: " + type);
+                failures += checkContentTypes("text/html", type);
             }
         } finally {
             Files.delete(file);
@@ -106,8 +159,7 @@
             String type = Files.probeContentType(file);
             if (type == null)
                 throw new RuntimeException("Custom file type detector not installed?");
-            if (!type.equals("grape/unknown"))
-                throw new RuntimeException("Unexpected type: " + type);
+            failures += checkContentTypes("grape/unknown", type);
         } finally {
             Files.delete(file);
         }
@@ -122,7 +174,11 @@
                 "image/jpeg", "audio/mpeg", "video/mp4", "application/pdf",
                 "image/png"
             };
-            checkContentTypes(extensions, expectedTypes);
+            failures += checkOSXContentTypes(extensions, expectedTypes);
+        }
+
+        if (failures > 0) {
+            throw new RuntimeException("Test failed!");
         }
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/jar/JarFile/MultiReleaseJarAPI.java	Thu Feb 25 11:27:30 2016 -0800
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2015, 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 8132734
+ * @summary Test the extended API and the aliasing additions in JarFile that
+ *          support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarAPI
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import static java.util.jar.JarFile.Release;
+import static sun.misc.Version.jdkMajorVersion;  // fixme JEP 223 Version
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class MultiReleaseJarAPI {
+    String userdir = System.getProperty("user.dir",".");
+    File unversioned = new File(userdir, "unversioned.jar");
+    File multirelease = new File(userdir, "multi-release.jar");
+    File signedmultirelease = new File(userdir, "signed-multi-release.jar");
+    Release[] values = JarFile.Release.values();
+
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildUnversionedJar();
+        creator.buildMultiReleaseJar();
+        creator.buildSignedMultiReleaseJar();
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(unversioned.toPath());
+        Files.delete(multirelease.toPath());
+        Files.delete(signedmultirelease.toPath());
+    }
+
+    @Test
+    public void isMultiReleaseJar() throws Exception {
+        try (JarFile jf = new JarFile(unversioned)) {
+            Assert.assertFalse(jf.isMultiRelease());
+        }
+
+        try (JarFile jf = new JarFile(multirelease)) {
+            Assert.assertTrue(jf.isMultiRelease());
+        }
+    }
+
+    @Test
+    public void testVersioning() throws Exception {
+        // multi-release jar
+        JarFile jar = new JarFile(multirelease);
+        Assert.assertEquals(Release.BASE, jar.getVersion());
+        jar.close();
+
+        for (Release value : values) {
+            System.err.println("test versioning for Release " + value);
+            try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) {
+                Assert.assertEquals(value, jf.getVersion());
+            }
+        }
+
+        // regular, unversioned, jar
+        for (Release value : values) {
+            try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) {
+                Assert.assertEquals(Release.BASE, jf.getVersion());
+            }
+        }
+
+        // assure that we have a Release object corresponding to the actual runtime version
+        String version = "VERSION_" + jdkMajorVersion();
+        boolean runtimeVersionExists = false;
+        for (Release value : values) {
+            if (version.equals(value.name())) runtimeVersionExists = true;
+        }
+        Assert.assertTrue(runtimeVersionExists);
+    }
+
+    @Test
+    public void testAliasing() throws Exception {
+        for (Release value : values) {
+            System.err.println("test aliasing for Release " + value);
+            String name = value.name();
+            String prefix;
+            if (name.equals("BASE")) {
+                prefix = "";
+            } else if (name.equals("RUNTIME")) {
+                prefix = "META-INF/versions/" + jdkMajorVersion() + "/";
+            } else {
+                prefix = "META-INF/versions/" + name.substring(8) + "/";
+            }
+            // test both multi-release jars
+            readAndCompare(multirelease, value, "README", prefix + "README");
+            readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class");
+            // and signed multi-release jars
+            readAndCompare(signedmultirelease, value, "README", prefix + "README");
+            readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class");
+        }
+    }
+
+    private void readAndCompare(File jar, Release version, String name, String realName) throws Exception {
+        byte[] baseBytes;
+        byte[] versionedBytes;
+        try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) {
+            ZipEntry ze = jf.getEntry(realName);
+            try (InputStream is = jf.getInputStream(ze)) {
+                baseBytes = is.readAllBytes();
+            }
+        }
+        assert baseBytes.length > 0;
+
+        try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) {
+            ZipEntry ze = jf.getEntry(name);
+            try (InputStream is = jf.getInputStream(ze)) {
+                versionedBytes = is.readAllBytes();
+            }
+        }
+        assert versionedBytes.length > 0;
+
+        Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes));
+    }
+
+    @Test
+    public void testNames() throws Exception {
+        String rname = "version/Version.class";
+        String vname = "META-INF/versions/9/version/Version.class";
+        ZipEntry ze1;
+        ZipEntry ze2;
+        try (JarFile jf = new JarFile(multirelease)) {
+            ze1 = jf.getEntry(vname);
+        }
+        Assert.assertEquals(ze1.getName(), vname);
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+            ze2 = jf.getEntry(rname);
+        }
+        Assert.assertEquals(ze2.getName(), rname);
+        Assert.assertNotEquals(ze1.getName(), ze2.getName());
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java	Thu Feb 25 11:27:30 2016 -0800
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, 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 8132734
+ * @summary Test the System properties for JarFile that support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties
+ */
+
+import com.sun.net.httpserver.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties {
+    private SimpleHttpServer server;
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        server = new SimpleHttpServer();
+        server.start();
+        super.initialize();
+    }
+
+    @Override
+    protected void initializeClassLoader() throws Exception {
+        URL[] urls = new URL[]{
+                new URL("http://localhost:" + server.getPort() + "/multi-release-jar")
+        };
+        cldr = new URLClassLoader(urls);
+        // load any class, Main is convenient and in the root entries
+        rootClass = cldr.loadClass("version.Main");
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        // Windows requires server to stop before file is deleted
+        if (server != null)
+            server.stop();
+        super.close();
+    }
+
+    /*
+     * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
+     */
+
+    @Test
+    public void testURLClassLoader() throws Throwable {
+        Class<?> vcls = cldr.loadClass("version.Version");
+        invokeMethod(vcls, rtVersion);
+    }
+
+    @Test
+    public void testGetResourceAsStream() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use rootClass as a base for getting resources
+        getResourceAsStream(rootClass, resource);
+    }
+
+    @Test
+    public void testGetResource() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use rootClass as a base for getting resources
+        getResource(rootClass, resource);
+    }
+}
+
+/**
+ * Extremely simple server that only performs one task.  The server listens for
+ * requests on the ephemeral port.  If it sees a request that begins with
+ * "/multi-release-jar", it consumes the request and returns a stream of bytes
+ * representing the jar file multi-release.jar found in "userdir".
+ */
+class SimpleHttpServer {
+    private static final String userdir = System.getProperty("user.dir", ".");
+    private static final Path multirelease = Paths.get(userdir, "multi-release.jar");
+
+    private final HttpServer server;
+
+    public SimpleHttpServer() throws IOException {
+        server = HttpServer.create();
+    }
+
+    public void start() throws IOException {
+        server.bind(new InetSocketAddress(0), 0);
+        server.createContext("/multi-release-jar", t -> {
+            try (InputStream is = t.getRequestBody()) {
+                is.readAllBytes();  // probably not necessary to consume request
+                byte[] bytes = Files.readAllBytes(multirelease);
+                t.sendResponseHeaders(200, bytes.length);
+                try (OutputStream os = t.getResponseBody()) {
+                    os.write(bytes);
+                }
+            }
+        });
+        server.setExecutor(null); // creates a default executor
+        server.start();
+    }
+
+    public void stop() {
+        server.stop(0);
+    }
+
+    int getPort() {
+        return server.getAddress().getPort();
+    }
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/jar/JarFile/MultiReleaseJarIterators.java	Thu Feb 25 11:27:30 2016 -0800
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2015, 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 8132734
+ * @summary Test the extended API and the aliasing additions in JarFile that
+ *          support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarIterators
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
+import java.util.zip.ZipFile;
+
+import static java.util.jar.JarFile.Release;
+import static sun.misc.Version.jdkMajorVersion;  // fixme JEP 223 Version
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+public class MultiReleaseJarIterators {
+    String userdir = System.getProperty("user.dir", ".");
+    File unversioned = new File(userdir, "unversioned.jar");
+    File multirelease = new File(userdir, "multi-release.jar");
+    Map<String,JarEntry> uvEntries = new HashMap<>();
+    Map<String,JarEntry> mrEntries = new HashMap<>();
+    Map<String,JarEntry> baseEntries = new HashMap<>();
+    Map<String,JarEntry> v9Entries = new HashMap<>();
+    Map<String, JarEntry> v10Entries = new HashMap<>();
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildUnversionedJar();
+        creator.buildMultiReleaseJar();
+
+        try (JarFile jf = new JarFile(multirelease)) {
+            for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
+                JarEntry je = e.nextElement();
+                String name = je.getName();
+                mrEntries.put(name, je);
+                if (name.startsWith("META-INF/versions/")) {
+                    if (name.startsWith("META-INF/versions/9/")) {
+                        v9Entries.put(name.substring(20), je);
+                    } else if (name.startsWith("META-INF/versions/10/")) {
+                        v10Entries.put(name.substring(21), je);
+                    }
+                } else {
+                    baseEntries.put(name, je);
+                }
+            }
+        }
+        Assert.assertEquals(mrEntries.size(), 14);
+        Assert.assertEquals(baseEntries.size(), 6);
+        Assert.assertEquals(v9Entries.size(), 5);
+        Assert.assertEquals(v10Entries.size(), 3);
+
+        try (JarFile jf = new JarFile(unversioned)) {
+            jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je));
+        }
+        Assert.assertEquals(uvEntries.size(), 6);
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(unversioned.toPath());
+        Files.delete(multirelease.toPath());
+    }
+
+    @Test
+    public void testMultiReleaseJar() throws IOException {
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) {
+            testEnumeration(jf, mrEntries);
+            testStream(jf, mrEntries);
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) {
+            testEnumeration(jf, baseEntries);
+            testStream(jf, baseEntries);
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+            testEnumeration(jf, v9Entries);
+            testStream(jf, v9Entries);
+        }
+
+        try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            Map<String,JarEntry> expectedEntries;
+            switch (jdkMajorVersion()) {
+                case 9:
+                    expectedEntries = v9Entries;
+                    break;
+                case 10:  // won't get here until JDK 10
+                    expectedEntries = v10Entries;
+                    break;
+                default:
+                    expectedEntries = baseEntries;
+                    break;
+            }
+
+            testEnumeration(jf, expectedEntries);
+            testStream(jf, expectedEntries);
+        }
+    }
+
+    @Test
+    public void testUnversionedJar() throws IOException {
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+
+        try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) {
+            testEnumeration(jf, uvEntries);
+            testStream(jf, uvEntries);
+        }
+    }
+
+    private void testEnumeration(JarFile jf, Map<String,JarEntry> expectedEntries) {
+        Map<String, JarEntry> actualEntries = new HashMap<>();
+        for (Enumeration<JarEntry> e = jf.entries(); e.hasMoreElements(); ) {
+            JarEntry je = e.nextElement();
+            actualEntries.put(je.getName(), je);
+        }
+
+        testEntries(jf, actualEntries, expectedEntries);
+    }
+
+
+    private void testStream(JarFile jf, Map<String,JarEntry> expectedEntries) {
+        Map<String,JarEntry> actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je));
+
+        testEntries(jf, actualEntries, expectedEntries);
+    }
+
+    private void testEntries(JarFile jf, Map<String,JarEntry> actualEntries, Map<String,JarEntry> expectedEntries) {
+        /* For multi-release jar files constructed with a Release object,
+         * actualEntries contain versionedEntries that are considered part of the
+         * public API.  They have a 1-1 correspondence with baseEntries,
+         * so entries that are not part of the public API won't be present,
+         * i.e. those entries with a name that starts with version/PackagePrivate
+         * in this particular jar file (multi-release.jar)
+         */
+
+        Map<String,JarEntry> entries;
+        if (expectedEntries == mrEntries) {
+            Assert.assertEquals(actualEntries.size(), mrEntries.size());
+            entries = mrEntries;
+        } else if (expectedEntries == uvEntries) {
+            Assert.assertEquals(actualEntries.size(), uvEntries.size());
+            entries = uvEntries;
+        } else {
+            Assert.assertEquals(actualEntries.size(), baseEntries.size());  // this is correct
+            entries = baseEntries;
+        }
+
+        entries.keySet().forEach(name -> {
+            JarEntry ee = expectedEntries.get(name);
+            if (ee == null) ee = entries.get(name);
+            JarEntry ae = actualEntries.get(name);
+            try {
+                compare(jf, ae, ee);
+            } catch (IOException x) {
+                throw new RuntimeException(x);
+            }
+        });
+    }
+
+    private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException {
+        byte[] abytes;
+        byte[] ebytes;
+
+        try (InputStream is = jf.getInputStream(actual)) {
+            abytes = is.readAllBytes();
+        }
+
+        try (InputStream is = jf.getInputStream(expected)) {
+            ebytes = is.readAllBytes();
+        }
+
+        Assert.assertEquals(abytes, ebytes);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/jar/JarFile/MultiReleaseJarProperties.java	Thu Feb 25 11:27:30 2016 -0800
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2015, 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 8132734
+ * @summary Test the System properties for JarFile that support multi-release jar files
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties
+ * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.file.Files;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+import static sun.misc.Version.jdkMajorVersion;  // fixme JEP 223 Version
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarProperties {
+    final static int ROOTVERSION = 8; // magic number from knowledge of internals
+    final static String userdir = System.getProperty("user.dir", ".");
+    final static File multirelease = new File(userdir, "multi-release.jar");
+    protected int rtVersion;
+    boolean force;
+    protected ClassLoader cldr;
+    protected Class<?> rootClass;
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildMultiReleaseJar();
+
+        rtVersion = Integer.getInteger("jdk.util.jar.version", jdkMajorVersion());
+        String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", "");
+        if (mrprop.equals("false")) {
+            rtVersion = ROOTVERSION;
+        } else if (rtVersion < ROOTVERSION) {
+            rtVersion = ROOTVERSION;
+        } else if (rtVersion > jdkMajorVersion()) {
+            rtVersion = jdkMajorVersion();
+        }
+        force = mrprop.equals("force");
+
+        initializeClassLoader();
+    }
+
+    protected void initializeClassLoader() throws Exception {
+        URL[] urls = new URL[]{multirelease.toURI().toURL()};
+        cldr = new URLClassLoader(urls);
+        // load any class, Main is convenient and in the root entries
+        rootClass = cldr.loadClass("version.Main");
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        ((URLClassLoader)cldr).close();
+        Files.delete(multirelease.toPath());
+    }
+
+    /*
+     * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader
+     */
+    @Test
+    public void testURLClassLoader() throws Throwable {
+        Class<?> vcls = cldr.loadClass("version.Version");
+        invokeMethod(vcls, rtVersion);
+    }
+
+    protected void invokeMethod(Class<?> vcls, int expected) throws Throwable {
+        MethodType mt = MethodType.methodType(int.class);
+        MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt);
+        Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance()));
+    }
+
+    /*
+     * jdk.util.jar.enableMultiRelease=force should affect a custom class loader
+     */
+    @Test
+    public void testClassLoader() throws Throwable {
+        try (JarFile jf = new JarFile(multirelease)) {  // do not set runtime versioning
+            ClassLoader cldr = new CustomClassLoader(jf);
+            Class<?> vcls = cldr.loadClass("version.Version");
+            if (rtVersion == 9) {
+                try {
+                    cldr.loadClass("version.PackagePrivate");
+                } catch (ClassNotFoundException x) {
+                    if (force) throw x;
+                }
+            }
+            invokeMethod(vcls, force ? rtVersion : ROOTVERSION);
+        }
+    }
+
+    private static class CustomClassLoader extends ClassLoader {
+        private final JarFile jf;
+
+        CustomClassLoader(JarFile jf) throws Exception {
+            super(null);
+            this.jf = jf;
+        }
+
+        protected Class<?> findClass(String name) throws ClassNotFoundException {
+            try {
+                byte[] b;
+                String entryName = name.replace(".", "/") + ".class";
+                JarEntry je = jf.getJarEntry(entryName);
+                if (je != null) {
+                    try (InputStream is = jf.getInputStream(je)) {
+                        b = new byte[(int) je.getSize()];
+                        is.read(b);
+                    }
+                    return defineClass(name, b, 0, b.length);
+                }
+                throw new ClassNotFoundException(name);
+            } catch (IOException x) {
+                throw new ClassNotFoundException(x.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public void testGetResourceAsStream() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use fileRootClass as a base for getting resources
+        getResourceAsStream(rootClass, resource);
+    }
+
+    protected void getResourceAsStream(Class<?> rootClass, String resource) throws Exception {
+        try (InputStream is = rootClass.getResourceAsStream(resource)) {
+            byte[] bytes = is.readAllBytes();
+            resource = new String(bytes);
+        }
+        String match = "return " + rtVersion + ";";
+        Assert.assertTrue(resource.contains(match));
+    }
+
+    @Test
+    public void testGetResource() throws Exception {
+        String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java";
+        // use rootClass as a base for getting resources
+        getResource(rootClass, resource);
+    }
+
+    protected void getResource(Class<?> rootClass, String resource) throws Exception {
+        URL url = rootClass.getResource(resource);
+        try (InputStream is = url.openStream()) {
+            byte[] bytes = is.readAllBytes();
+            resource = new String(bytes);
+        }
+        String match = "return " + rtVersion + ";";
+        Assert.assertTrue(resource.contains(match));
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java	Thu Feb 25 11:27:30 2016 -0800
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2015, 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 8132734
+ * @summary Test potential security related issues
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarSecurity
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.CodeSigner;
+import java.security.cert.Certificate;
+import java.util.Arrays;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.zip.ZipFile;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarSecurity {
+    String userdir = System.getProperty("user.dir",".");
+    File multirelease = new File(userdir, "multi-release.jar");
+    File signedmultirelease = new File(userdir, "signed-multi-release.jar");
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator =  new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildMultiReleaseJar();
+        creator.buildSignedMultiReleaseJar();
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(multirelease.toPath());
+        Files.delete(signedmultirelease.toPath());
+    }
+
+    @Test
+    public void testCertsAndSigners() throws IOException {
+        try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) {
+            int version = sun.misc.Version.jdkMajorVersion();  // fixme JEP 223 Version
+            CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class"));
+            CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + version + "/version/Version.class"));
+            Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates()));
+            Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners()));
+        }
+    }
+
+    private static class CertsAndSigners {
+        final private JarFile jf;
+        final private JarEntry je;
+        private boolean readComplete;
+
+        CertsAndSigners(JarFile jf, JarEntry je) {
+            this.jf = jf;
+            this.je = je;
+        }
+
+        Certificate[] getCertificates() throws IOException {
+            readEntry();
+            return je.getCertificates();
+        }
+
+        CodeSigner[] getCodeSigners() throws IOException {
+            readEntry();
+            return je.getCodeSigners();
+        }
+
+        private void readEntry() throws IOException {
+            if (!readComplete) {
+                try (InputStream is = jf.getInputStream(je)) {
+                    is.readAllBytes();
+                }
+                readComplete = true;
+            }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/javax/crypto/JceSecurity/FinalRestricted.java	Thu Feb 25 11:27:30 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/test/jdk/internal/misc/Unsafe/CopySwap.java	Thu Feb 25 11:27:30 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/test/sun/misc/SunMiscSignalTest.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/sun/misc/SunMiscSignalTest.java	Thu Feb 25 11:27:30 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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java	Thu Feb 25 11:27:30 2016 -0800
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2015, 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 8132734
+ * @summary Test that URL connections to multi-release jars can be runtime versioned
+ * @library /lib/testlibrary/java/util/jar
+ * @build Compiler JarBuilder CreateMultiReleaseTestJars
+ * @run testng MultiReleaseJarURLConnection
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.JarURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.jar.JarFile;
+
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+public class MultiReleaseJarURLConnection {
+    String userdir = System.getProperty("user.dir",".");
+    String urlFile = "jar:file:" + userdir + "/multi-release.jar!/";
+    String urlEntry = urlFile + "version/Version.java";
+
+    @BeforeClass
+    public void initialize() throws Exception {
+        CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars();
+        creator.compileEntries();
+        creator.buildMultiReleaseJar();
+    }
+
+    @AfterClass
+    public void close() throws IOException {
+        Files.delete(Paths.get(userdir, "multi-release.jar"));
+    }
+
+    @Test
+    public void testRuntimeVersioning() throws Exception {
+        Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
+        // #runtime is "magic"
+        Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9"));
+        // #fragment or any other fragment is not magic
+        Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8"));
+        // cached entities not affected
+        Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8"));
+    }
+
+    @Test
+    public void testCachedJars() throws Exception {
+        URL rootUrl = new URL(urlFile);
+        JarURLConnection juc = (JarURLConnection)rootUrl.openConnection();
+        JarFile rootJar = juc.getJarFile();
+        JarFile.Release root = rootJar.getVersion();
+
+        URL runtimeUrl = new URL(urlFile + "#runtime");
+        juc = (JarURLConnection)runtimeUrl.openConnection();
+        JarFile runtimeJar = juc.getJarFile();
+        JarFile.Release runtime = runtimeJar.getVersion();
+        Assert.assertNotEquals(root, runtime);
+
+        juc = (JarURLConnection)rootUrl.openConnection();
+        JarFile jar = juc.getJarFile();
+        Assert.assertEquals(jar.getVersion(), root);
+        Assert.assertEquals(jar, rootJar);
+
+        juc = (JarURLConnection)runtimeUrl.openConnection();
+        jar = juc.getJarFile();
+        Assert.assertEquals(jar.getVersion(), runtime);
+        Assert.assertEquals(jar, runtimeJar);
+
+        rootJar.close();
+        runtimeJar.close();
+        jar.close(); // probably not needed
+    }
+
+    private boolean readAndCompare(URL url, String match) throws Exception {
+        boolean result;
+        // necessary to do it this way, instead of openStream(), so we can
+        // close underlying JarFile, otherwise windows can't delete the file
+        URLConnection conn = url.openConnection();
+        try (InputStream is = conn.getInputStream()) {
+            byte[] bytes = is.readAllBytes();
+            result = (new String(bytes)).contains(match);
+        }
+        if (conn instanceof JarURLConnection) {
+            ((JarURLConnection)conn).getJarFile().close();
+        }
+        return result;
+    }
+}
--- a/test/tools/pack200/Pack200Test.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/tools/pack200/Pack200Test.java	Thu Feb 25 11:27:30 2016 -0800
@@ -81,7 +81,9 @@
                 System.out.println("Packing [" + in.toString() + "]");
                 // Call the packer
                 Utils.pack(jarFile, packFile);
+                System.out.println("Done Packing [" + in.toString() + "]");
                 jarFile.close();
+                System.out.println("Start leak check");
                 leakCheck();
 
                 System.out.println("  Unpacking using java unpacker");
--- a/test/tools/pack200/Utils.java	Thu Feb 25 09:41:46 2016 -0800
+++ b/test/tools/pack200/Utils.java	Thu Feb 25 11:27:30 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2014, 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
@@ -324,6 +324,9 @@
     private static void findFiles0(File startDir, List<File> list,
                                     FileFilter filter) throws IOException {
         File[] foundFiles = startDir.listFiles(filter);
+        if (foundFiles == null) {
+            return;
+        }
         list.addAll(Arrays.asList(foundFiles));
         File[] dirs = startDir.listFiles(DIR_FILTER);
         for (File dir : dirs) {