Merge epsilon-gc-branch
authorshade
Mon, 23 Apr 2018 12:32:25 +0200
branchepsilon-gc-branch
changeset 56472 02bd022fcea1
parent 56461 d661341c153a (current diff)
parent 49849 2aa32bb6f3dc (diff)
child 56473 63a5ea2cdd0d
Merge
src/hotspot/share/memory/universe.cpp
src/hotspot/share/runtime/globals.hpp
src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java
src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c
src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java
src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java
test/hotspot/jtreg/TEST.groups
--- a/.hgtags	Thu Apr 19 15:37:43 2018 +0200
+++ b/.hgtags	Mon Apr 23 12:32:25 2018 +0200
@@ -481,3 +481,4 @@
 755e1b55a4dff510f9639cdb5c5e82549a7e09b3 jdk-11+8
 0c3e252cea44f06aef570ef464950ab97c669970 jdk-11+9
 6fa770f9f8ab296e1ce255ec17ccf6d4e1051886 jdk-10+46
+69d7398038c54774d9395b6810e0cca335edc02c jdk-11+10
--- a/make/Init.gmk	Thu Apr 19 15:37:43 2018 +0200
+++ b/make/Init.gmk	Mon Apr 23 12:32:25 2018 +0200
@@ -310,9 +310,13 @@
           ifneq ($(PARALLEL_TARGETS), )
 	    $(call StartGlobalTimer)
 	    $(call PrepareSmartJavac)
+            # JOBS will only be empty for a bootcycle-images recursive call
+            # or if specified via a make argument directly. In those cases
+            # treat it as NOT using jobs at all.
 	    ( cd $(TOPDIR) && \
 	        $(NICE) $(MAKE) $(MAKE_ARGS) $(OUTPUT_SYNC_FLAG) \
-	            -j $(JOBS) -f make/Main.gmk $(USER_MAKE_VARS) \
+                    $(if $(JOBS), -j $(JOBS)) \
+	            -f make/Main.gmk $(USER_MAKE_VARS) \
 	            $(PARALLEL_TARGETS) $(COMPARE_BUILD_MAKE) $(BUILD_LOG_PIPE) || \
 	        ( exitcode=$$? && \
 	        $(PRINTF) "\nERROR: Build failed for $(TARGET_DESCRIPTION) (exit code $$exitcode) \n" \
--- a/make/autoconf/flags.m4	Thu Apr 19 15:37:43 2018 +0200
+++ b/make/autoconf/flags.m4	Mon Apr 23 12:32:25 2018 +0200
@@ -233,15 +233,17 @@
   # The sysroot flags are needed for configure to be able to run the compilers
   FLAGS_SETUP_SYSROOT_FLAGS
 
+  # For solstudio and xlc, the word size flag is required for correct behavior.
+  # For clang/gcc, the flag is only strictly required for reduced builds, but
+  # set it always where possible (x86, sparc and ppc).
   if test "x$TOOLCHAIN_TYPE" = xxlc; then
     MACHINE_FLAG="-q${OPENJDK_TARGET_CPU_BITS}"
-  elif test "x$TOOLCHAIN_TYPE" != xmicrosoft; then
-    if test "x$OPENJDK_TARGET_CPU" != xaarch64 &&
-       test "x$OPENJDK_TARGET_CPU" != xarm &&
-       test "x$OPENJDK_TARGET_CPU" != xmips &&
-       test "x$OPENJDK_TARGET_CPU" != xmipsel &&
-       test "x$OPENJDK_TARGET_CPU" != xmips64 &&
-       test "x$OPENJDK_TARGET_CPU" != xmips64el; then
+  elif test "x$TOOLCHAIN_TYPE" = xsolstudio; then
+    MACHINE_FLAG="-m${OPENJDK_TARGET_CPU_BITS}"
+  elif test "x$TOOLCHAIN_TYPE" = xgcc || test "x$TOOLCHAIN_TYPE" = xclang; then
+    if test "x$OPENJDK_TARGET_CPU_ARCH" = xx86 ||
+        test "x$OPENJDK_TARGET_CPU_ARCH" = xsparc ||
+        test "x$OPENJDK_TARGET_CPU_ARCH" = xppc; then
       MACHINE_FLAG="-m${OPENJDK_TARGET_CPU_BITS}"
     fi
   fi
--- a/make/data/charsetmapping/charsets	Thu Apr 19 15:37:43 2018 +0200
+++ b/make/data/charsetmapping/charsets	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2000, 2018, 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
@@ -326,6 +326,8 @@
     ascii   true
     alias   cp1252			# JDK historical
     alias   cp5348			# Euro IBM CCSID
+    alias   ibm-1252
+    alias   ibm1252
 
 charset windows-1253 MS1253
     package sun.nio.cs
@@ -933,11 +935,16 @@
 
 charset x-IBM942C IBM942C
     package sun.nio.cs.ext
-    type    source
+    type    template
     alias   cp942C               # JDK historical
     alias   ibm942C
     alias   ibm-942C
     alias   942C
+    alias   cp932
+    alias   ibm932
+    alias   ibm-932
+    alias   932
+    alias   x-ibm932
 
 charset x-IBM943 IBM943
     package sun.nio.cs.ext
@@ -952,7 +959,7 @@
 
 charset x-IBM943C IBM943C
     package sun.nio.cs.ext
-    type    source
+    type    template
     alias   cp943C               # JDK historical
     alias   ibm943C
     alias   ibm-943C
@@ -1519,6 +1526,9 @@
     alias   ibm1383
     alias   ibm-1383
     alias   1383
+    alias   ibmeuccn
+    alias   ibm-euccn
+    alias   cpeuccn
 
 charset x-IBM970 IBM970
     package sun.nio.cs.ext
--- a/make/data/charsetmapping/stdcs-aix	Thu Apr 19 15:37:43 2018 +0200
+++ b/make/data/charsetmapping/stdcs-aix	Mon Apr 23 12:32:25 2018 +0200
@@ -1,6 +1,26 @@
 #
 #   generate these charsets into sun.nio.cs
 #
+Big5
+Big5_Solaris
+Big5_HKSCS
 EUC_CN
 EUC_KR
 GBK
+GB18030
+IBM856
+IBM921
+IBM922
+IBM942
+IBM942C
+IBM943
+IBM943C
+IBM950
+IBM970
+IBM1046
+IBM1124
+IBM1383
+ISO_8859_6
+ISO_8859_8
+MS1252
+TIS_620
--- a/make/jdk/src/classes/build/tools/charsetmapping/SPI.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/make/jdk/src/classes/build/tools/charsetmapping/SPI.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 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
@@ -129,7 +129,7 @@
                      } else if (line.indexOf("_INCLUDE_ALIASES_MAP_") != -1) {
                          Hasher.genClass(out, aliasKeys, aliasValues,
                                          null, "Aliases", "String",
-                                         11, 3, true, false, false);
+                                         12, 3, true, false, false);
                      } else if (line.indexOf("_INCLUDE_CLASSES_MAP_") != -1) {
                          Hasher.genClass(out, clzKeys, clzValues,
                                          null, "Classes", "String",
--- a/make/lib/Awt2dLibraries.gmk	Thu Apr 19 15:37:43 2018 +0200
+++ b/make/lib/Awt2dLibraries.gmk	Mon Apr 23 12:32:25 2018 +0200
@@ -224,7 +224,7 @@
         format-nonliteral parentheses, \
     DISABLED_WARNINGS_clang := logical-op-parentheses extern-initializer, \
     DISABLED_WARNINGS_solstudio := E_DECLARATION_IN_CODE, \
-    DISABLED_WARNINGS_microsoft := 4297 4244 4267 4996, \
+    DISABLED_WARNINGS_microsoft := 4297 4244 4267 4291 4302 4311 4996, \
     ASFLAGS := $(LIBAWT_ASFLAGS), \
     LDFLAGS := $(LDFLAGS_JDKLIB) $(call SET_SHARED_LIBRARY_ORIGIN), \
     LDFLAGS_macosx := -L$(INSTALL_LIBRARIES_HERE), \
--- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2014, Red Hat Inc. All rights reserved.
+ * Copyright (c) 2014, 2018, Red Hat Inc. 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
@@ -133,9 +133,29 @@
     address addr = MacroAssembler::target_addr_for_insn(instruction_address());
     *(intptr_t*)addr = x;
   } else {
+    // Store x into the instruction stream.
     MacroAssembler::pd_patch_instruction(instruction_address(), (address)x);
     ICache::invalidate_range(instruction_address(), instruction_size);
   }
+
+  // Find and replace the oop/metadata corresponding to this
+  // instruction in oops section.
+  CodeBlob* cb = CodeCache::find_blob(instruction_address());
+  nmethod* nm = cb->as_nmethod_or_null();
+  if (nm != NULL) {
+    RelocIterator iter(nm, instruction_address(), next_instruction_address());
+    while (iter.next()) {
+      if (iter.type() == relocInfo::oop_type) {
+        oop* oop_addr = iter.oop_reloc()->oop_addr();
+        *oop_addr = cast_to_oop(x);
+        break;
+      } else if (iter.type() == relocInfo::metadata_type) {
+        Metadata** metadata_addr = iter.metadata_reloc()->metadata_addr();
+        *metadata_addr = (Metadata*)x;
+        break;
+      }
+    }
+  }
 }
 
 void NativeMovConstReg::print() {
--- a/src/hotspot/cpu/arm/methodHandles_arm.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/cpu/arm/methodHandles_arm.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -35,6 +35,7 @@
 #include "memory/resourceArea.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/frame.inline.hpp"
+#include "utilities/preserveException.hpp"
 
 #define __ _masm->
 
--- a/src/hotspot/cpu/arm/relocInfo_arm.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/cpu/arm/relocInfo_arm.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -29,6 +29,7 @@
 #include "nativeInst_arm.hpp"
 #include "oops/compressedOops.inline.hpp"
 #include "oops/oop.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/safepoint.hpp"
 
 void Relocation::pd_set_data_value(address x, intptr_t o, bool verify_only) {
--- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -24,6 +24,7 @@
  */
 
 #include "precompiled.hpp"
+#include "asm/macroAssembler.inline.hpp"
 #include "gc/shared/barrierSetAssembler.hpp"
 #include "interpreter/interp_masm.hpp"
 
--- a/src/hotspot/share/aot/aotCodeHeap.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/aot/aotCodeHeap.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -445,6 +445,8 @@
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_handle_wrong_method_stub", address, SharedRuntime::get_handle_wrong_method_stub());
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_exception_handler_for_return_address", address, SharedRuntime::exception_handler_for_return_address);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_register_finalizer", address, SharedRuntime::register_finalizer);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_object_notify", address, JVMCIRuntime::object_notify);
+    SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_object_notifyAll", address, JVMCIRuntime::object_notifyAll);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_OSR_migration_end", address, SharedRuntime::OSR_migration_end);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_dynamic_invoke", address, CompilerRuntime::resolve_dynamic_invoke);
     SET_AOT_GLOBAL_SYMBOL_VALUE("_aot_resolve_string_by_symbol", address, CompilerRuntime::resolve_string_by_symbol);
--- a/src/hotspot/share/aot/aotLoader.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/aot/aotLoader.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -183,28 +183,21 @@
     // Shifts are static values which initialized by 0 until java heap initialization.
     // AOT libs are loaded before heap initialized so shift values are not set.
     // It is okay since ObjectAlignmentInBytes flag which defines shifts value is set before AOT libs are loaded.
-    // Set shifts value based on first AOT library config.
+    // AOT sets shift values during heap and metaspace initialization.
+    // Check shifts value to make sure thay did not change.
     if (UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) {
       int oop_shift = Universe::narrow_oop_shift();
-      if (oop_shift == 0) {
-        Universe::set_narrow_oop_shift(AOTLib::narrow_oop_shift());
-      } else {
-        FOR_ALL_AOT_LIBRARIES(lib) {
-          (*lib)->verify_flag(AOTLib::narrow_oop_shift(), oop_shift, "Universe::narrow_oop_shift");
-        }
+      FOR_ALL_AOT_LIBRARIES(lib) {
+        (*lib)->verify_flag((*lib)->config()->_narrowOopShift, oop_shift, "Universe::narrow_oop_shift");
       }
       if (UseCompressedClassPointers) { // It is set only if UseCompressedOops is set
         int klass_shift = Universe::narrow_klass_shift();
-        if (klass_shift == 0) {
-          Universe::set_narrow_klass_shift(AOTLib::narrow_klass_shift());
-        } else {
-          FOR_ALL_AOT_LIBRARIES(lib) {
-            (*lib)->verify_flag(AOTLib::narrow_klass_shift(), klass_shift, "Universe::narrow_klass_shift");
-          }
+        FOR_ALL_AOT_LIBRARIES(lib) {
+          (*lib)->verify_flag((*lib)->config()->_narrowKlassShift, klass_shift, "Universe::narrow_klass_shift");
         }
       }
     }
-    // Create heaps for all the libraries
+    // Create heaps for all valid libraries
     FOR_ALL_AOT_LIBRARIES(lib) {
       if ((*lib)->is_valid()) {
         AOTCodeHeap* heap = new AOTCodeHeap(*lib);
@@ -213,6 +206,9 @@
           add_heap(heap);
           CodeCache::add_heap(heap);
         }
+      } else {
+        // Unload invalid libraries
+        os::dll_unload((*lib)->dl_handle());
       }
     }
   }
@@ -223,20 +219,29 @@
   }
 }
 
+// Set shift value for compressed oops and classes based on first AOT library config.
+// AOTLoader::universe_init(), which is called later, will check the shift value again to make sure nobody change it.
+// This code is not executed during CDS dump because it runs in Interpreter mode and AOT is disabled in this mode.
+
+void AOTLoader::set_narrow_oop_shift() {
+  // This method is called from Universe::initialize_heap().
+  if (UseAOT && libraries_count() > 0 &&
+      UseCompressedOops && AOTLib::narrow_oop_shift_initialized()) {
+    if (Universe::narrow_oop_shift() == 0) {
+      // 0 is valid shift value for small heap but we can safely increase it
+      // at this point when nobody used it yet.
+      Universe::set_narrow_oop_shift(AOTLib::narrow_oop_shift());
+    }
+  }
+}
+
 void AOTLoader::set_narrow_klass_shift() {
-  // This method could be called from Metaspace::set_narrow_klass_base_and_shift().
-  // In case it is not called (during dump CDS, for example) the corresponding code in
-  // AOTLoader::universe_init(), which is called later, will set the shift value.
+  // This method is called from Metaspace::set_narrow_klass_base_and_shift().
   if (UseAOT && libraries_count() > 0 &&
       UseCompressedOops && AOTLib::narrow_oop_shift_initialized() &&
       UseCompressedClassPointers) {
-    int klass_shift = Universe::narrow_klass_shift();
-    if (klass_shift == 0) {
+    if (Universe::narrow_klass_shift() == 0) {
       Universe::set_narrow_klass_shift(AOTLib::narrow_klass_shift());
-    } else {
-      FOR_ALL_AOT_LIBRARIES(lib) {
-        (*lib)->verify_flag(AOTLib::narrow_klass_shift(), klass_shift, "Universe::narrow_klass_shift");
-      }
     }
   }
 }
--- a/src/hotspot/share/aot/aotLoader.hpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/aot/aotLoader.hpp	Mon Apr 23 12:32:25 2018 +0200
@@ -57,6 +57,7 @@
   static void initialize() NOT_AOT({ FLAG_SET_ERGO(bool, UseAOT, false); });
 
   static void universe_init() NOT_AOT_RETURN;
+  static void set_narrow_oop_shift() NOT_AOT_RETURN;
   static void set_narrow_klass_shift() NOT_AOT_RETURN;
   static bool contains(address p) NOT_AOT({ return false; });
   static void load_for_klass(InstanceKlass* ik, Thread* thread) NOT_AOT_RETURN;
--- a/src/hotspot/share/classfile/classLoader.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/classfile/classLoader.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -80,13 +80,13 @@
 
 // Entry points in zip.dll for loading zip/jar file entries
 
-typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
-typedef void (JNICALL *ZipClose_t)(jzfile *zip);
-typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
-typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
-typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
-typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
-typedef jint     (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
+typedef void * * (*ZipOpen_t)(const char *name, char **pmsg);
+typedef void (*ZipClose_t)(jzfile *zip);
+typedef jzentry* (*FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
+typedef jboolean (*ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
+typedef jzentry* (*GetNextEntry_t)(jzfile *zip, jint n);
+typedef jboolean (*ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
+typedef jint     (*Crc32_t)(jint crc, const jbyte *buf, jint len);
 
 static ZipOpen_t         ZipOpen            = NULL;
 static ZipClose_t        ZipClose           = NULL;
--- a/src/hotspot/share/compiler/compileBroker.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/compiler/compileBroker.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -50,6 +50,7 @@
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
 #include "runtime/javaCalls.hpp"
+#include "runtime/jniHandles.inline.hpp"
 #include "runtime/os.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -117,6 +118,17 @@
 // The installed compiler(s)
 AbstractCompiler* CompileBroker::_compilers[2];
 
+// The maximum numbers of compiler threads to be determined during startup.
+int CompileBroker::_c1_count = 0;
+int CompileBroker::_c2_count = 0;
+
+// An array of compiler names as Java String objects
+jobject* CompileBroker::_compiler1_objects = NULL;
+jobject* CompileBroker::_compiler2_objects = NULL;
+
+CompileLog** CompileBroker::_compiler1_logs = NULL;
+CompileLog** CompileBroker::_compiler2_logs = NULL;
+
 // These counters are used to assign an unique ID to each compilation.
 volatile jint CompileBroker::_compilation_id     = 0;
 volatile jint CompileBroker::_osr_compilation_id = 0;
@@ -287,6 +299,36 @@
 }
 
 /**
+ * Check if a CompilerThread can be removed and update count if requested.
+ */
+static bool can_remove(CompilerThread *ct, bool do_it) {
+  assert(UseDynamicNumberOfCompilerThreads, "or shouldn't be here");
+  if (!ReduceNumberOfCompilerThreads) return false;
+
+  AbstractCompiler *compiler = ct->compiler();
+  int compiler_count = compiler->num_compiler_threads();
+  bool c1 = compiler->is_c1();
+
+  // Keep at least 1 compiler thread of each type.
+  if (compiler_count < 2) return false;
+
+  // Keep thread alive for at least some time.
+  if (ct->idle_time_millis() < (c1 ? 500 : 100)) return false;
+
+  // We only allow the last compiler thread of each type to get removed.
+  jobject last_compiler = c1 ? CompileBroker::compiler1_object(compiler_count - 1)
+                             : CompileBroker::compiler2_object(compiler_count - 1);
+  if (oopDesc::equals(ct->threadObj(), JNIHandles::resolve_non_null(last_compiler))) {
+    if (do_it) {
+      assert_locked_or_safepoint(CompileThread_lock); // Update must be consistent.
+      compiler->set_num_compiler_threads(compiler_count - 1);
+    }
+    return true;
+  }
+  return false;
+}
+
+/**
  * Add a CompileTask to a CompileQueue.
  */
 void CompileQueue::add(CompileTask* task) {
@@ -383,6 +425,11 @@
     // is disabled forever. We use 5 seconds wait time; the exiting of compiler threads
     // is not critical and we do not want idle compiler threads to wake up too often.
     MethodCompileQueue_lock->wait(!Mutex::_no_safepoint_check_flag, 5*1000);
+
+    if (UseDynamicNumberOfCompilerThreads && _first == NULL) {
+      // Still nothing to compile. Give caller a chance to stop this thread.
+      if (can_remove(CompilerThread::current(), false)) return NULL;
+    }
   }
 
   if (CompileBroker::is_compilation_disabled_forever()) {
@@ -532,8 +579,8 @@
     return;
   }
   // Set the interface to the current compiler(s).
-  int c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple);
-  int c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization);
+  _c1_count = CompilationPolicy::policy()->compiler_count(CompLevel_simple);
+  _c2_count = CompilationPolicy::policy()->compiler_count(CompLevel_full_optimization);
 
 #if INCLUDE_JVMCI
   if (EnableJVMCI) {
@@ -545,35 +592,35 @@
       if (FLAG_IS_DEFAULT(JVMCIThreads)) {
         if (BootstrapJVMCI) {
           // JVMCI will bootstrap so give it more threads
-          c2_count = MIN2(32, os::active_processor_count());
+          _c2_count = MIN2(32, os::active_processor_count());
         }
       } else {
-        c2_count = JVMCIThreads;
+        _c2_count = JVMCIThreads;
       }
       if (FLAG_IS_DEFAULT(JVMCIHostThreads)) {
       } else {
-        c1_count = JVMCIHostThreads;
+        _c1_count = JVMCIHostThreads;
       }
     }
   }
 #endif // INCLUDE_JVMCI
 
 #ifdef COMPILER1
-  if (c1_count > 0) {
+  if (_c1_count > 0) {
     _compilers[0] = new Compiler();
   }
 #endif // COMPILER1
 
 #ifdef COMPILER2
   if (true JVMCI_ONLY( && !UseJVMCICompiler)) {
-    if (c2_count > 0) {
+    if (_c2_count > 0) {
       _compilers[1] = new C2Compiler();
     }
   }
 #endif // COMPILER2
 
   // Start the compiler thread(s) and the sweeper thread
-  init_compiler_sweeper_threads(c1_count, c2_count);
+  init_compiler_sweeper_threads();
   // totalTime performance counter is always created as it is required
   // by the implementation of java.lang.management.CompilationMBean.
   {
@@ -679,29 +726,38 @@
   _initialized = true;
 }
 
-JavaThread* CompileBroker::make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters,
-                                       AbstractCompiler* comp, bool compiler_thread, TRAPS) {
-  JavaThread* thread = NULL;
-  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_Thread(), true, CHECK_0);
+Handle CompileBroker::create_thread_oop(const char* name, TRAPS) {
+  Klass* k = SystemDictionary::find(vmSymbols::java_lang_Thread(), Handle(), Handle(), CHECK_NH);
+  assert(k != NULL, "must be initialized");
   InstanceKlass* klass = InstanceKlass::cast(k);
-  instanceHandle thread_oop = klass->allocate_instance_handle(CHECK_0);
-  Handle string = java_lang_String::create_from_str(name, CHECK_0);
+  instanceHandle thread_handle = klass->allocate_instance_handle(CHECK_NH);
+  Handle string = java_lang_String::create_from_str(name, CHECK_NH);
 
   // Initialize thread_oop to put it into the system threadGroup
-  Handle thread_group (THREAD,  Universe::system_thread_group());
+  Handle thread_group(THREAD, Universe::system_thread_group());
   JavaValue result(T_VOID);
-  JavaCalls::call_special(&result, thread_oop,
+  JavaCalls::call_special(&result, thread_handle,
                        klass,
                        vmSymbols::object_initializer_name(),
                        vmSymbols::threadgroup_string_void_signature(),
                        thread_group,
                        string,
-                       CHECK_0);
+                       CHECK_NH);
+
+  return thread_handle;
+}
 
+
+JavaThread* CompileBroker::make_thread(jobject thread_handle, CompileQueue* queue,
+                                       AbstractCompiler* comp, bool compiler_thread, TRAPS) {
+  JavaThread* thread = NULL;
   {
     MutexLocker mu(Threads_lock, THREAD);
     if (compiler_thread) {
-      thread = new CompilerThread(queue, counters);
+      if (!InjectCompilerCreationFailure || comp->num_compiler_threads() == 0) {
+        CompilerCounters* counters = new CompilerCounters();
+        thread = new CompilerThread(queue, counters);
+      }
     } else {
       thread = new CodeCacheSweeperThread();
     }
@@ -720,13 +776,13 @@
 
     if (thread != NULL && thread->osthread() != NULL) {
 
-      java_lang_Thread::set_thread(thread_oop(), thread);
+      java_lang_Thread::set_thread(JNIHandles::resolve_non_null(thread_handle), thread);
 
       // Note that this only sets the JavaThread _priority field, which by
       // definition is limited to Java priorities and not OS priorities.
       // The os-priority is set in the CompilerThread startup code itself
 
-      java_lang_Thread::set_priority(thread_oop(), NearMaxPriority);
+      java_lang_Thread::set_priority(JNIHandles::resolve_non_null(thread_handle), NearMaxPriority);
 
       // Note that we cannot call os::set_priority because it expects Java
       // priorities and we are *explicitly* using OS priorities so that it's
@@ -743,9 +799,9 @@
       }
       os::set_native_priority(thread, native_prio);
 
-      java_lang_Thread::set_daemon(thread_oop());
+      java_lang_Thread::set_daemon(JNIHandles::resolve_non_null(thread_handle));
 
-      thread->set_threadObj(thread_oop());
+      thread->set_threadObj(JNIHandles::resolve_non_null(thread_handle));
       if (compiler_thread) {
         thread->as_CompilerThread()->set_compiler(comp);
       }
@@ -756,6 +812,12 @@
 
   // First release lock before aborting VM.
   if (thread == NULL || thread->osthread() == NULL) {
+    if (UseDynamicNumberOfCompilerThreads && comp->num_compiler_threads() > 0) {
+      if (thread != NULL) {
+        thread->smr_delete();
+      }
+      return NULL;
+    }
     vm_exit_during_initialization("java.lang.OutOfMemoryError",
                                   os::native_thread_creation_failed_msg());
   }
@@ -767,51 +829,123 @@
 }
 
 
-void CompileBroker::init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count) {
+void CompileBroker::init_compiler_sweeper_threads() {
   EXCEPTION_MARK;
 #if !defined(ZERO)
-  assert(c2_compiler_count > 0 || c1_compiler_count > 0, "No compilers?");
+  assert(_c2_count > 0 || _c1_count > 0, "No compilers?");
 #endif // !ZERO
   // Initialize the compilation queue
-  if (c2_compiler_count > 0) {
+  if (_c2_count > 0) {
     const char* name = JVMCI_ONLY(UseJVMCICompiler ? "JVMCI compile queue" :) "C2 compile queue";
     _c2_compile_queue  = new CompileQueue(name);
-    _compilers[1]->set_num_compiler_threads(c2_compiler_count);
+    _compiler2_objects = NEW_C_HEAP_ARRAY(jobject, _c2_count, mtCompiler);
+    _compiler2_logs = NEW_C_HEAP_ARRAY(CompileLog*, _c2_count, mtCompiler);
   }
-  if (c1_compiler_count > 0) {
+  if (_c1_count > 0) {
     _c1_compile_queue  = new CompileQueue("C1 compile queue");
-    _compilers[0]->set_num_compiler_threads(c1_compiler_count);
+    _compiler1_objects = NEW_C_HEAP_ARRAY(jobject, _c1_count, mtCompiler);
+    _compiler1_logs = NEW_C_HEAP_ARRAY(CompileLog*, _c1_count, mtCompiler);
   }
 
-  int compiler_count = c1_compiler_count + c2_compiler_count;
+  char name_buffer[256];
 
-  char name_buffer[256];
-  const bool compiler_thread = true;
-  for (int i = 0; i < c2_compiler_count; i++) {
+  for (int i = 0; i < _c2_count; i++) {
     // Create a name for our thread.
     sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i);
-    CompilerCounters* counters = new CompilerCounters();
-    make_thread(name_buffer, _c2_compile_queue, counters, _compilers[1], compiler_thread, CHECK);
+    jobject thread_handle = JNIHandles::make_global(create_thread_oop(name_buffer, THREAD));
+    _compiler2_objects[i] = thread_handle;
+    _compiler2_logs[i] = NULL;
+
+    if (!UseDynamicNumberOfCompilerThreads || i == 0) {
+      JavaThread *ct = make_thread(thread_handle, _c2_compile_queue, _compilers[1], /* compiler_thread */ true, CHECK);
+      assert(ct != NULL, "should have been handled for initial thread");
+      _compilers[1]->set_num_compiler_threads(i + 1);
+      if (TraceCompilerThreads) {
+        ResourceMark rm;
+        MutexLocker mu(Threads_lock);
+        tty->print_cr("Added initial compiler thread %s", ct->get_thread_name());
+      }
+    }
   }
 
-  for (int i = c2_compiler_count; i < compiler_count; i++) {
+  for (int i = 0; i < _c1_count; i++) {
     // Create a name for our thread.
     sprintf(name_buffer, "C1 CompilerThread%d", i);
-    CompilerCounters* counters = new CompilerCounters();
-    // C1
-    make_thread(name_buffer, _c1_compile_queue, counters, _compilers[0], compiler_thread, CHECK);
+    jobject thread_handle = JNIHandles::make_global(create_thread_oop(name_buffer, THREAD));
+    _compiler1_objects[i] = thread_handle;
+    _compiler1_logs[i] = NULL;
+
+    if (!UseDynamicNumberOfCompilerThreads || i == 0) {
+      JavaThread *ct = make_thread(thread_handle, _c1_compile_queue, _compilers[0], /* compiler_thread */ true, CHECK);
+      assert(ct != NULL, "should have been handled for initial thread");
+      _compilers[0]->set_num_compiler_threads(i + 1);
+      if (TraceCompilerThreads) {
+        ResourceMark rm;
+        MutexLocker mu(Threads_lock);
+        tty->print_cr("Added initial compiler thread %s", ct->get_thread_name());
+      }
+    }
   }
 
   if (UsePerfData) {
-    PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, compiler_count, CHECK);
+    PerfDataManager::create_constant(SUN_CI, "threads", PerfData::U_Bytes, _c1_count + _c2_count, CHECK);
   }
 
   if (MethodFlushing) {
     // Initialize the sweeper thread
-    make_thread("Sweeper thread", NULL, NULL, NULL, false, CHECK);
+    jobject thread_handle = JNIHandles::make_local(THREAD, create_thread_oop("Sweeper thread", THREAD)());
+    make_thread(thread_handle, NULL, NULL, /* compiler_thread */ false, CHECK);
   }
 }
 
+void CompileBroker::possibly_add_compiler_threads() {
+  EXCEPTION_MARK;
+
+  julong available_memory = os::available_memory();
+  // Only do attempt to start additional threads if the lock is free.
+  if (!CompileThread_lock->try_lock()) return;
+
+  if (_c2_compile_queue != NULL) {
+    int old_c2_count = _compilers[1]->num_compiler_threads();
+    int new_c2_count = MIN3(_c2_count,
+        _c2_compile_queue->size() / 2,
+        (int)(available_memory / 200*M));
+
+    for (int i = old_c2_count; i < new_c2_count; i++) {
+      JavaThread *ct = make_thread(compiler2_object(i), _c2_compile_queue, _compilers[1], true, CHECK);
+      if (ct == NULL) break;
+      _compilers[1]->set_num_compiler_threads(i + 1);
+      if (TraceCompilerThreads) {
+        ResourceMark rm;
+        MutexLocker mu(Threads_lock);
+        tty->print_cr("Added compiler thread %s (available memory: %dMB)",
+                      ct->get_thread_name(), (int)(available_memory/M));
+      }
+    }
+  }
+
+  if (_c1_compile_queue != NULL) {
+    int old_c1_count = _compilers[0]->num_compiler_threads();
+    int new_c1_count = MIN3(_c1_count,
+        _c1_compile_queue->size() / 4,
+        (int)(available_memory / 100*M));
+
+    for (int i = old_c1_count; i < new_c1_count; i++) {
+      JavaThread *ct = make_thread(compiler1_object(i), _c1_compile_queue, _compilers[0], true, CHECK);
+      if (ct == NULL) break;
+      _compilers[0]->set_num_compiler_threads(i + 1);
+      if (TraceCompilerThreads) {
+        ResourceMark rm;
+        MutexLocker mu(Threads_lock);
+        tty->print_cr("Added compiler thread %s (available memory: %dMB)",
+                      ct->get_thread_name(), (int)(available_memory/M));
+      }
+    }
+  }
+
+  CompileThread_lock->unlock();
+}
+
 
 /**
  * Set the methods on the stack as on_stack so that redefine classes doesn't
@@ -1546,6 +1680,49 @@
   }
 }
 
+/**
+ * Helper function to create new or reuse old CompileLog.
+ */
+CompileLog* CompileBroker::get_log(CompilerThread* ct) {
+  if (!LogCompilation) return NULL;
+
+  AbstractCompiler *compiler = ct->compiler();
+  bool c1 = compiler->is_c1();
+  jobject* compiler_objects = c1 ? _compiler1_objects : _compiler2_objects;
+  assert(compiler_objects != NULL, "must be initialized at this point");
+  CompileLog** logs = c1 ? _compiler1_logs : _compiler2_logs;
+  assert(logs != NULL, "must be initialized at this point");
+  int count = c1 ? _c1_count : _c2_count;
+
+  // Find Compiler number by its threadObj.
+  oop compiler_obj = ct->threadObj();
+  int compiler_number = 0;
+  bool found = false;
+  for (; compiler_number < count; compiler_number++) {
+    if (oopDesc::equals(JNIHandles::resolve_non_null(compiler_objects[compiler_number]), compiler_obj)) {
+      found = true;
+      break;
+    }
+  }
+  assert(found, "Compiler must exist at this point");
+
+  // Determine pointer for this thread's log.
+  CompileLog** log_ptr = &logs[compiler_number];
+
+  // Return old one if it exists.
+  CompileLog* log = *log_ptr;
+  if (log != NULL) {
+    ct->init_log(log);
+    return log;
+  }
+
+  // Create a new one and remember it.
+  init_compiler_thread_log();
+  log = ct->log();
+  *log_ptr = log;
+  return log;
+}
+
 // ------------------------------------------------------------------
 // CompileBroker::compiler_thread_loop
 //
@@ -1568,10 +1745,7 @@
   }
 
   // Open a log.
-  if (LogCompilation) {
-    init_compiler_thread_log();
-  }
-  CompileLog* log = thread->log();
+  CompileLog* log = get_log(thread);
   if (log != NULL) {
     log->begin_elem("start_compile_thread name='%s' thread='" UINTX_FORMAT "' process='%d'",
                     thread->name(),
@@ -1586,6 +1760,8 @@
     return;
   }
 
+  thread->start_idle_timer();
+
   // Poll for new compilation tasks as long as the JVM runs. Compilation
   // should only be disabled if something went wrong while initializing the
   // compiler runtimes. This, in turn, should not happen. The only known case
@@ -1597,9 +1773,24 @@
 
     CompileTask* task = queue->get();
     if (task == NULL) {
+      if (UseDynamicNumberOfCompilerThreads) {
+        // Access compiler_count under lock to enforce consistency.
+        MutexLocker only_one(CompileThread_lock);
+        if (can_remove(thread, true)) {
+          if (TraceCompilerThreads) {
+            tty->print_cr("Removing compiler thread %s after " JLONG_FORMAT " ms idle time",
+                          thread->name(), thread->idle_time_millis());
+          }
+          return; // Stop this thread.
+        }
+      }
       continue;
     }
 
+    if (UseDynamicNumberOfCompilerThreads) {
+      possibly_add_compiler_threads();
+    }
+
     // Give compiler threads an extra quanta.  They tend to be bursty and
     // this helps the compiler to finish up the job.
     if (CompilerThreadHintNoPreempt) {
@@ -1618,6 +1809,7 @@
       // Compile the method.
       if ((UseCompiler || AlwaysCompileLoopMethods) && CompileBroker::should_compile_new_jobs()) {
         invoke_compiler_on_method(task);
+        thread->start_idle_timer();
       } else {
         // After compilation is disabled, remove remaining methods from queue
         method->clear_queued_for_compilation();
--- a/src/hotspot/share/compiler/compileBroker.hpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/compiler/compileBroker.hpp	Mon Apr 23 12:32:25 2018 +0200
@@ -161,6 +161,15 @@
   // The installed compiler(s)
   static AbstractCompiler* _compilers[2];
 
+  // The maximum numbers of compiler threads to be determined during startup.
+  static int _c1_count, _c2_count;
+
+  // An array of compiler thread Java objects
+  static jobject *_compiler1_objects, *_compiler2_objects;
+
+  // An array of compiler logs
+  static CompileLog **_compiler1_logs, **_compiler2_logs;
+
   // These counters are used for assigning id's to each compilation
   static volatile jint _compilation_id;
   static volatile jint _osr_compilation_id;
@@ -219,8 +228,11 @@
 
   static volatile int _print_compilation_warning;
 
-  static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS);
-  static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count);
+  static Handle create_thread_oop(const char* name, TRAPS);
+  static JavaThread* make_thread(jobject thread_oop, CompileQueue* queue,
+                                 AbstractCompiler* comp, bool compiler_thread, TRAPS);
+  static void init_compiler_sweeper_threads();
+  static void possibly_add_compiler_threads();
   static bool compilation_is_complete  (const methodHandle& method, int osr_bci, int comp_level);
   static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded);
   static void preload_classes          (const methodHandle& method, TRAPS);
@@ -367,6 +379,21 @@
   // compiler name for debugging
   static const char* compiler_name(int comp_level);
 
+  // Provide access to compiler thread Java objects
+  static jobject compiler1_object(int idx) {
+    assert(_compiler1_objects != NULL, "must be initialized");
+    assert(idx < _c1_count, "oob");
+    return _compiler1_objects[idx];
+  }
+
+  static jobject compiler2_object(int idx) {
+    assert(_compiler2_objects != NULL, "must be initialized");
+    assert(idx < _c2_count, "oob");
+    return _compiler2_objects[idx];
+  }
+
+  static CompileLog* get_log(CompilerThread* ct);
+
   static int get_total_compile_count() {          return _total_compile_count; }
   static int get_total_bailout_count() {          return _total_bailout_count; }
   static int get_total_invalidated_count() {      return _total_invalidated_count; }
--- a/src/hotspot/share/jvmci/jvmciRuntime.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -415,6 +415,34 @@
   }
 JRT_END
 
+// Object.notify() fast path, caller does slow path
+JRT_LEAF(jboolean, JVMCIRuntime::object_notify(JavaThread *thread, oopDesc* obj))
+
+  // Very few notify/notifyAll operations find any threads on the waitset, so
+  // the dominant fast-path is to simply return.
+  // Relatedly, it's critical that notify/notifyAll be fast in order to
+  // reduce lock hold times.
+  if (!SafepointSynchronize::is_synchronizing()) {
+    if (ObjectSynchronizer::quick_notify(obj, thread, false)) {
+      return true;
+    }
+  }
+  return false; // caller must perform slow path
+
+JRT_END
+
+// Object.notifyAll() fast path, caller does slow path
+JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread *thread, oopDesc* obj))
+
+  if (!SafepointSynchronize::is_synchronizing() ) {
+    if (ObjectSynchronizer::quick_notify(obj, thread, true)) {
+      return true;
+    }
+  }
+  return false; // caller must perform slow path
+
+JRT_END
+
 JRT_ENTRY(void, JVMCIRuntime::throw_and_post_jvmti_exception(JavaThread* thread, const char* exception, const char* message))
   TempNewSymbol symbol = SymbolTable::new_symbol(exception, CHECK);
   SharedRuntime::throw_and_post_jvmti_exception(thread, symbol, message);
--- a/src/hotspot/share/jvmci/jvmciRuntime.hpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp	Mon Apr 23 12:32:25 2018 +0200
@@ -139,6 +139,8 @@
   static address exception_handler_for_pc(JavaThread* thread);
   static void monitorenter(JavaThread* thread, oopDesc* obj, BasicLock* lock);
   static void monitorexit (JavaThread* thread, oopDesc* obj, BasicLock* lock);
+  static jboolean object_notify(JavaThread* thread, oopDesc* obj);
+  static jboolean object_notifyAll(JavaThread* thread, oopDesc* obj);
   static void vm_error(JavaThread* thread, jlong where, jlong format, jlong value);
   static oopDesc* load_and_clear_exception(JavaThread* thread);
   static void log_printf(JavaThread* thread, oopDesc* format, jlong v1, jlong v2, jlong v3);
--- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -625,6 +625,8 @@
   declare_function(JVMCIRuntime::exception_handler_for_pc) \
   declare_function(JVMCIRuntime::monitorenter) \
   declare_function(JVMCIRuntime::monitorexit) \
+  declare_function(JVMCIRuntime::object_notify) \
+  declare_function(JVMCIRuntime::object_notifyAll) \
   declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \
   declare_function(JVMCIRuntime::throw_klass_external_name_exception) \
   declare_function(JVMCIRuntime::throw_class_cast_exception) \
--- a/src/hotspot/share/memory/universe.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/memory/universe.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -786,6 +786,7 @@
       // Did reserve heap below 32Gb. Can use base == 0;
       Universe::set_narrow_oop_base(0);
     }
+    AOTLoader::set_narrow_oop_shift();
 
     Universe::set_narrow_ptrs_base(Universe::narrow_oop_base());
 
--- a/src/hotspot/share/prims/jvm.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/prims/jvm.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -2768,15 +2768,14 @@
   return len;
 }
 
-
 // HotSpot specific jio method
-void jio_print(const char* s) {
+void jio_print(const char* s, size_t len) {
   // Try to make this function as atomic as possible.
   if (Arguments::vfprintf_hook() != NULL) {
-    jio_fprintf(defaultStream::output_stream(), "%s", s);
+    jio_fprintf(defaultStream::output_stream(), "%.*s", (int)len, s);
   } else {
     // Make an unused local variable to avoid warning from gcc 4.x compiler.
-    size_t count = ::write(defaultStream::output_fd(), s, (int)strlen(s));
+    size_t count = ::write(defaultStream::output_fd(), s, (int)len);
   }
 }
 
--- a/src/hotspot/share/runtime/globals.hpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/runtime/globals.hpp	Mon Apr 23 12:32:25 2018 +0200
@@ -1486,6 +1486,20 @@
           range(0, max_jint)                                                \
           constraint(CICompilerCountConstraintFunc, AfterErgo)              \
                                                                             \
+  product(bool, UseDynamicNumberOfCompilerThreads, true,                    \
+          "Dynamically choose the number of parallel compiler threads")     \
+                                                                            \
+  diagnostic(bool, ReduceNumberOfCompilerThreads, true,                     \
+             "Reduce the number of parallel compiler threads when they "    \
+             "are not used")                                                \
+                                                                            \
+  diagnostic(bool, TraceCompilerThreads, false,                             \
+             "Trace creation and removal of compiler threads")              \
+                                                                            \
+  develop(bool, InjectCompilerCreationFailure, false,                       \
+          "Inject thread creation failures for "                            \
+          "UseDynamicNumberOfCompilerThreads")                              \
+                                                                            \
   product(intx, CompilationPolicyChoice, 0,                                 \
           "which compilation policy (0-3)")                                 \
           range(0, 3)                                                       \
--- a/src/hotspot/share/runtime/thread.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/runtime/thread.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -1495,7 +1495,6 @@
 jlong* JavaThread::_jvmci_old_thread_counters;
 
 bool jvmci_counters_include(JavaThread* thread) {
-  oop threadObj = thread->threadObj();
   return !JVMCICountersExcludeCompiler || !thread->is_Compiler_thread();
 }
 
@@ -3360,6 +3359,11 @@
 #endif
 }
 
+CompilerThread::~CompilerThread() {
+  // Delete objects which were allocated on heap.
+  delete _counters;
+}
+
 bool CompilerThread::can_call_java() const {
   return _compiler != NULL && _compiler->is_jvmci();
 }
--- a/src/hotspot/share/runtime/thread.hpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/runtime/thread.hpp	Mon Apr 23 12:32:25 2018 +0200
@@ -2029,12 +2029,14 @@
   BufferBlob*           _buffer_blob;
 
   AbstractCompiler*     _compiler;
+  TimeStamp             _idle_time;
 
  public:
 
   static CompilerThread* current();
 
   CompilerThread(CompileQueue* queue, CompilerCounters* counters);
+  ~CompilerThread();
 
   bool is_Compiler_thread() const                { return true; }
 
@@ -2064,6 +2066,11 @@
     _log = log;
   }
 
+  void start_idle_timer()                        { _idle_time.update(); }
+  jlong idle_time_millis() {
+    return TimeHelper::counter_to_millis(_idle_time.ticks_since_update());
+  }
+
 #ifndef PRODUCT
  private:
   IdealGraphPrinter *_ideal_graph_printer;
--- a/src/hotspot/share/utilities/ostream.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/hotspot/share/utilities/ostream.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -36,7 +36,9 @@
 #include "utilities/vmError.hpp"
 #include "utilities/xmlstream.hpp"
 
-extern "C" void jio_print(const char* s); // Declarationtion of jvm method
+// Declarations of jvm methods
+extern "C" void jio_print(const char* s, size_t len);
+extern "C" int jio_printf(const char *fmt, ...);
 
 outputStream::outputStream(int width) {
   _width       = width;
@@ -612,19 +614,15 @@
 
   // Try again to open the file in the temp directory.
   delete file;
-  char warnbuf[O_BUFLEN*2];
-  jio_snprintf(warnbuf, sizeof(warnbuf), "Warning:  Cannot open log file: %s\n", log_name);
-  // Note:  This feature is for maintainer use only.  No need for L10N.
-  jio_print(warnbuf);
+  // Note: This feature is for maintainer use only.  No need for L10N.
+  jio_printf("Warning:  Cannot open log file: %s\n", log_name);
   try_name = make_log_name(log_name, os::get_temp_directory());
   if (try_name == NULL) {
     warning("Cannot open file %s: file name is too long for directory %s.\n", log_name, os::get_temp_directory());
     return NULL;
   }
 
-  jio_snprintf(warnbuf, sizeof(warnbuf),
-               "Warning:  Forcing option -XX:LogFile=%s\n", try_name);
-  jio_print(warnbuf);
+  jio_printf("Warning:  Forcing option -XX:LogFile=%s\n", try_name);
 
   file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
   FREE_C_HEAP_ARRAY(char, try_name);
@@ -824,20 +822,6 @@
   tty_lock->unlock();
 }
 
-
-// Yuck:  jio_print does not accept char*/len.
-static void call_jio_print(const char* s, size_t len) {
-  char buffer[O_BUFLEN+100];
-  if (len > sizeof(buffer)-1) {
-    warning("increase O_BUFLEN in ostream.cpp -- output truncated");
-    len = sizeof(buffer)-1;
-  }
-  strncpy(buffer, s, len);
-  buffer[len] = '\0';
-  jio_print(buffer);
-}
-
-
 void defaultStream::write(const char* s, size_t len) {
   intx thread_id = os::current_thread_id();
   intx holder = hold(thread_id);
@@ -845,11 +829,7 @@
   if (DisplayVMOutput &&
       (_outer_xmlStream == NULL || !_outer_xmlStream->inside_attrs())) {
     // print to output stream. It can be redirected by a vfprintf hook
-    if (s[len] == '\0') {
-      jio_print(s);
-    } else {
-      call_jio_print(s, len);
-    }
+    jio_print(s, len);
   }
 
   // print to log file
--- a/src/java.base/share/classes/java/util/zip/Deflater.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/classes/java/util/zip/Deflater.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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
@@ -26,7 +26,13 @@
 package java.util.zip;
 
 import java.lang.ref.Cleaner.Cleanable;
+import java.lang.ref.Reference;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.Objects;
+
 import jdk.internal.ref.CleanerFactory;
+import sun.nio.ch.DirectBuffer;
 
 /**
  * This class provides support for general purpose compression using the
@@ -35,8 +41,14 @@
  * protected by patents. It is fully described in the specifications at
  * the <a href="package-summary.html#package.description">java.util.zip
  * package description</a>.
- *
- * <p>The following code fragment demonstrates a trivial compression
+ * <p>
+ * This class deflates sequences of bytes into ZLIB compressed data format.
+ * The input byte sequence is provided in either byte array or byte buffer,
+ * via one of the {@code setInput()} methods. The output byte sequence is
+ * written to the output byte array or byte buffer passed to the
+ * {@code deflate()} methods.
+ * <p>
+ * The following code fragment demonstrates a trivial compression
  * and decompression of a string using {@code Deflater} and
  * {@code Inflater}.
  *
@@ -92,8 +104,9 @@
 public class Deflater {
 
     private final DeflaterZStreamRef zsRef;
-    private byte[] buf = new byte[0];
-    private int off, len;
+    private ByteBuffer input = ZipUtils.defaultBuf;
+    private byte[] inputArray;
+    private int inputPos, inputLim;
     private int level, strategy;
     private boolean setParams;
     private boolean finish, finished;
@@ -170,9 +183,14 @@
      */
     public static final int FULL_FLUSH = 3;
 
+    /**
+     * Flush mode to use at the end of output.  Can only be provided by the
+     * user by way of {@link #finish()}.
+     */
+    private static final int FINISH = 4;
+
     static {
         ZipUtils.loadLibrary();
-        initIDs();
     }
 
     /**
@@ -208,59 +226,70 @@
     }
 
     /**
-     * Sets input data for compression. This should be called whenever
-     * needsInput() returns true indicating that more input data is required.
-     * @param b the input data bytes
+     * Sets input data for compression.
+     * <p>
+     * One of the {@code setInput()} methods should be called whenever
+     * {@code needsInput()} returns true indicating that more input data
+     * is required.
+     * <p>
+     * @param input the input data bytes
      * @param off the start offset of the data
      * @param len the length of the data
      * @see Deflater#needsInput
      */
-    public void setInput(byte[] b, int off, int len) {
-        if (b== null) {
-            throw new NullPointerException();
-        }
-        if (off < 0 || len < 0 || off > b.length - len) {
+    public void setInput(byte[] input, int off, int len) {
+        if (off < 0 || len < 0 || off > input.length - len) {
             throw new ArrayIndexOutOfBoundsException();
         }
         synchronized (zsRef) {
-            this.buf = b;
-            this.off = off;
-            this.len = len;
+            this.input = null;
+            this.inputArray = input;
+            this.inputPos = off;
+            this.inputLim = off + len;
         }
     }
 
     /**
-     * Sets input data for compression. This should be called whenever
-     * needsInput() returns true indicating that more input data is required.
-     * @param b the input data bytes
+     * Sets input data for compression.
+     * <p>
+     * One of the {@code setInput()} methods should be called whenever
+     * {@code needsInput()} returns true indicating that more input data
+     * is required.
+     * <p>
+     * @param input the input data bytes
      * @see Deflater#needsInput
      */
-    public void setInput(byte[] b) {
-        setInput(b, 0, b.length);
+    public void setInput(byte[] input) {
+        setInput(input, 0, input.length);
     }
 
     /**
-     * Sets preset dictionary for compression. A preset dictionary is used
-     * when the history buffer can be predetermined. When the data is later
-     * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
-     * in order to get the Adler-32 value of the dictionary required for
-     * decompression.
-     * @param b the dictionary data bytes
-     * @param off the start offset of the data
-     * @param len the length of the data
-     * @see Inflater#inflate
-     * @see Inflater#getAdler
+     * Sets input data for compression.
+     * <p>
+     * One of the {@code setInput()} methods should be called whenever
+     * {@code needsInput()} returns true indicating that more input data
+     * is required.
+     * <p>
+     * The given buffer's position will be advanced as deflate
+     * operations are performed, up to the buffer's limit.
+     * The input buffer may be modified (refilled) between deflate
+     * operations; doing so is equivalent to creating a new buffer
+     * and setting it with this method.
+     * <p>
+     * Modifying the input buffer's contents, position, or limit
+     * concurrently with an deflate operation will result in
+     * undefined behavior, which may include incorrect operation
+     * results or operation failure.
+     *
+     * @param input the input data bytes
+     * @see Deflater#needsInput
+     * @since 11
      */
-    public void setDictionary(byte[] b, int off, int len) {
-        if (b == null) {
-            throw new NullPointerException();
-        }
-        if (off < 0 || len < 0 || off > b.length - len) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
+    public void setInput(ByteBuffer input) {
+        Objects.requireNonNull(input);
         synchronized (zsRef) {
-            ensureOpen();
-            setDictionary(zsRef.address(), b, off, len);
+            this.input = input;
+            this.inputArray = null;
         }
     }
 
@@ -270,12 +299,69 @@
      * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
      * in order to get the Adler-32 value of the dictionary required for
      * decompression.
-     * @param b the dictionary data bytes
+     * @param dictionary the dictionary data bytes
+     * @param off the start offset of the data
+     * @param len the length of the data
+     * @see Inflater#inflate
+     * @see Inflater#getAdler
+     */
+    public void setDictionary(byte[] dictionary, int off, int len) {
+        if (off < 0 || len < 0 || off > dictionary.length - len) {
+            throw new ArrayIndexOutOfBoundsException();
+        }
+        synchronized (zsRef) {
+            ensureOpen();
+            setDictionary(zsRef.address(), dictionary, off, len);
+        }
+    }
+
+    /**
+     * Sets preset dictionary for compression. A preset dictionary is used
+     * when the history buffer can be predetermined. When the data is later
+     * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
+     * in order to get the Adler-32 value of the dictionary required for
+     * decompression.
+     * @param dictionary the dictionary data bytes
      * @see Inflater#inflate
      * @see Inflater#getAdler
      */
-    public void setDictionary(byte[] b) {
-        setDictionary(b, 0, b.length);
+    public void setDictionary(byte[] dictionary) {
+        setDictionary(dictionary, 0, dictionary.length);
+    }
+
+    /**
+     * Sets preset dictionary for compression. A preset dictionary is used
+     * when the history buffer can be predetermined. When the data is later
+     * uncompressed with Inflater.inflate(), Inflater.getAdler() can be called
+     * in order to get the Adler-32 value of the dictionary required for
+     * decompression.
+     * <p>
+     * The bytes in given byte buffer will be fully consumed by this method.  On
+     * return, its position will equal its limit.
+     *
+     * @param dictionary the dictionary data bytes
+     * @see Inflater#inflate
+     * @see Inflater#getAdler
+     */
+    public void setDictionary(ByteBuffer dictionary) {
+        synchronized (zsRef) {
+            int position = dictionary.position();
+            int remaining = Math.max(dictionary.limit() - position, 0);
+            ensureOpen();
+            if (dictionary.isDirect()) {
+                long address = ((DirectBuffer) dictionary).address();
+                try {
+                    setDictionaryBuffer(zsRef.address(), address + position, remaining);
+                } finally {
+                    Reference.reachabilityFence(dictionary);
+                }
+            } else {
+                byte[] array = ZipUtils.getBufferArray(dictionary);
+                int offset = ZipUtils.getBufferOffset(dictionary);
+                setDictionary(zsRef.address(), array, offset + position, remaining);
+            }
+            dictionary.position(position + remaining);
+        }
     }
 
     /**
@@ -331,14 +417,17 @@
     }
 
     /**
-     * Returns true if the input data buffer is empty and setInput()
-     * should be called in order to provide more input.
+     * Returns true if no data remains in the input buffer. This can
+     * be used to determine if one of the {@code setInput()} methods should be
+     * called in order to provide more input.
+     *
      * @return true if the input data buffer is empty and setInput()
      * should be called in order to provide more input
      */
     public boolean needsInput() {
         synchronized (zsRef) {
-            return len <= 0;
+            ByteBuffer input = this.input;
+            return input == null ? inputLim == inputPos : ! input.hasRemaining();
         }
     }
 
@@ -375,14 +464,14 @@
      * yields the same result as the invocation of
      * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
      *
-     * @param b the buffer for the compressed data
+     * @param output the buffer for the compressed data
      * @param off the start offset of the data
      * @param len the maximum number of bytes of compressed data
      * @return the actual number of bytes of compressed data written to the
      *         output buffer
      */
-    public int deflate(byte[] b, int off, int len) {
-        return deflate(b, off, len, NO_FLUSH);
+    public int deflate(byte[] output, int off, int len) {
+        return deflate(output, off, len, NO_FLUSH);
     }
 
     /**
@@ -396,12 +485,32 @@
      * yields the same result as the invocation of
      * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
      *
-     * @param b the buffer for the compressed data
+     * @param output the buffer for the compressed data
      * @return the actual number of bytes of compressed data written to the
      *         output buffer
      */
-    public int deflate(byte[] b) {
-        return deflate(b, 0, b.length, NO_FLUSH);
+    public int deflate(byte[] output) {
+        return deflate(output, 0, output.length, NO_FLUSH);
+    }
+
+    /**
+     * Compresses the input data and fills specified buffer with compressed
+     * data. Returns actual number of bytes of compressed data. A return value
+     * of 0 indicates that {@link #needsInput() needsInput} should be called
+     * in order to determine if more input data is required.
+     *
+     * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
+     * An invocation of this method of the form {@code deflater.deflate(output)}
+     * yields the same result as the invocation of
+     * {@code deflater.deflate(output, Deflater.NO_FLUSH)}.
+     *
+     * @param output the buffer for the compressed data
+     * @return the actual number of bytes of compressed data written to the
+     *         output buffer
+     * @since 11
+     */
+    public int deflate(ByteBuffer output) {
+        return deflate(output, NO_FLUSH);
     }
 
     /**
@@ -441,7 +550,11 @@
      * repeatedly output to the output buffer every time this method is
      * invoked.
      *
-     * @param b the buffer for the compressed data
+     * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
+     * for input, the input buffer's position will be advanced by the number of bytes
+     * consumed by this operation.
+     *
+     * @param output the buffer for the compressed data
      * @param off the start offset of the data
      * @param len the maximum number of bytes of compressed data
      * @param flush the compression flush mode
@@ -451,25 +564,248 @@
      * @throws IllegalArgumentException if the flush mode is invalid
      * @since 1.7
      */
-    public int deflate(byte[] b, int off, int len, int flush) {
-        if (b == null) {
-            throw new NullPointerException();
+    public int deflate(byte[] output, int off, int len, int flush) {
+        if (off < 0 || len < 0 || off > output.length - len) {
+            throw new ArrayIndexOutOfBoundsException();
         }
-        if (off < 0 || len < 0 || off > b.length - len) {
-            throw new ArrayIndexOutOfBoundsException();
+        if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
+            throw new IllegalArgumentException();
         }
         synchronized (zsRef) {
             ensureOpen();
-            if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
-                flush == FULL_FLUSH) {
-                int thisLen = this.len;
-                int n = deflateBytes(zsRef.address(), b, off, len, flush);
-                bytesWritten += n;
-                bytesRead += (thisLen - this.len);
-                return n;
+
+            ByteBuffer input = this.input;
+            if (finish) {
+                // disregard given flush mode in this case
+                flush = FINISH;
+            }
+            int params;
+            if (setParams) {
+                // bit 0: true to set params
+                // bit 1-2: strategy (0, 1, or 2)
+                // bit 3-31: level (0..9 or -1)
+                params = 1 | strategy << 1 | level << 3;
+            } else {
+                params = 0;
+            }
+            int inputPos;
+            long result;
+            if (input == null) {
+                inputPos = this.inputPos;
+                result = deflateBytesBytes(zsRef.address(),
+                    inputArray, inputPos, inputLim - inputPos,
+                    output, off, len,
+                    flush, params);
+            } else {
+                inputPos = input.position();
+                int inputRem = Math.max(input.limit() - inputPos, 0);
+                if (input.isDirect()) {
+                    try {
+                        long inputAddress = ((DirectBuffer) input).address();
+                        result = deflateBufferBytes(zsRef.address(),
+                            inputAddress + inputPos, inputRem,
+                            output, off, len,
+                            flush, params);
+                    } finally {
+                        Reference.reachabilityFence(input);
+                    }
+                } else {
+                    byte[] inputArray = ZipUtils.getBufferArray(input);
+                    int inputOffset = ZipUtils.getBufferOffset(input);
+                    result = deflateBytesBytes(zsRef.address(),
+                        inputArray, inputOffset + inputPos, inputRem,
+                        output, off, len,
+                        flush, params);
+                }
+            }
+            int read = (int) (result & 0x7fff_ffffL);
+            int written = (int) (result >>> 31 & 0x7fff_ffffL);
+            if ((result >>> 62 & 1) != 0) {
+                finished = true;
+            }
+            if (params != 0 && (result >>> 63 & 1) == 0) {
+                setParams = false;
+            }
+            if (input != null) {
+                input.position(inputPos + read);
+            } else {
+                this.inputPos = inputPos + read;
             }
+            bytesWritten += written;
+            bytesRead += read;
+            return written;
+        }
+    }
+
+    /**
+     * Compresses the input data and fills the specified buffer with compressed
+     * data. Returns actual number of bytes of data compressed.
+     *
+     * <p>Compression flush mode is one of the following three modes:
+     *
+     * <ul>
+     * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
+     * to accumulate, before producing output, in order to achieve the best
+     * compression (should be used in normal use scenario). A return value
+     * of 0 in this flush mode indicates that {@link #needsInput()} should
+     * be called in order to determine if more input data is required.
+     *
+     * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
+     * to the specified output buffer, so that an inflater that works on
+     * compressed data can get all input data available so far (In particular
+     * the {@link #needsInput()} returns {@code true} after this invocation
+     * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
+     * may degrade compression for some compression algorithms and so it
+     * should be used only when necessary.
+     *
+     * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
+     * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
+     * that works on the compressed output data can restart from this point
+     * if previous compressed data has been damaged or if random access is
+     * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
+     * compression.
+     * </ul>
+     *
+     * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
+     * the return value is equal to the {@linkplain ByteBuffer#remaining() remaining space}
+     * of the buffer, this method should be invoked again with the same
+     * {@code flush} parameter and more output space. Make sure that
+     * the buffer has at least 6 bytes of remaining space to avoid the
+     * flush marker (5 bytes) being repeatedly output to the output buffer
+     * every time this method is invoked.
+     *
+     * <p>On success, the position of the given {@code output} byte buffer will be
+     * advanced by as many bytes as were produced by the operation, which is equal
+     * to the number returned by this method.
+     *
+     * <p>If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
+     * for input, the input buffer's position will be advanced by the number of bytes
+     * consumed by this operation.
+     *
+     * @param output the buffer for the compressed data
+     * @param flush the compression flush mode
+     * @return the actual number of bytes of compressed data written to
+     *         the output buffer
+     *
+     * @throws IllegalArgumentException if the flush mode is invalid
+     * @since 11
+     */
+    public int deflate(ByteBuffer output, int flush) {
+        if (output.isReadOnly()) {
+            throw new ReadOnlyBufferException();
+        }
+        if (flush != NO_FLUSH && flush != SYNC_FLUSH && flush != FULL_FLUSH) {
             throw new IllegalArgumentException();
         }
+        synchronized (zsRef) {
+            ensureOpen();
+
+            ByteBuffer input = this.input;
+            if (finish) {
+                // disregard given flush mode in this case
+                flush = FINISH;
+            }
+            int params;
+            if (setParams) {
+                // bit 0: true to set params
+                // bit 1-2: strategy (0, 1, or 2)
+                // bit 3-31: level (0..9 or -1)
+                params = 1 | strategy << 1 | level << 3;
+            } else {
+                params = 0;
+            }
+            int outputPos = output.position();
+            int outputRem = Math.max(output.limit() - outputPos, 0);
+            int inputPos;
+            long result;
+            if (input == null) {
+                inputPos = this.inputPos;
+                if (output.isDirect()) {
+                    long outputAddress = ((DirectBuffer) output).address();
+                    try {
+                        result = deflateBytesBuffer(zsRef.address(),
+                            inputArray, inputPos, inputLim - inputPos,
+                            outputAddress + outputPos, outputRem,
+                            flush, params);
+                    } finally {
+                        Reference.reachabilityFence(output);
+                    }
+                } else {
+                    byte[] outputArray = ZipUtils.getBufferArray(output);
+                    int outputOffset = ZipUtils.getBufferOffset(output);
+                    result = deflateBytesBytes(zsRef.address(),
+                        inputArray, inputPos, inputLim - inputPos,
+                        outputArray, outputOffset + outputPos, outputRem,
+                        flush, params);
+                }
+            } else {
+                inputPos = input.position();
+                int inputRem = Math.max(input.limit() - inputPos, 0);
+                if (input.isDirect()) {
+                    long inputAddress = ((DirectBuffer) input).address();
+                    try {
+                        if (output.isDirect()) {
+                            long outputAddress = outputPos + ((DirectBuffer) output).address();
+                            try {
+                                result = deflateBufferBuffer(zsRef.address(),
+                                    inputAddress + inputPos, inputRem,
+                                    outputAddress, outputRem,
+                                    flush, params);
+                            } finally {
+                                Reference.reachabilityFence(output);
+                            }
+                        } else {
+                            byte[] outputArray = ZipUtils.getBufferArray(output);
+                            int outputOffset = ZipUtils.getBufferOffset(output);
+                            result = deflateBufferBytes(zsRef.address(),
+                                inputAddress + inputPos, inputRem,
+                                outputArray, outputOffset + outputPos, outputRem,
+                                flush, params);
+                        }
+                    } finally {
+                        Reference.reachabilityFence(input);
+                    }
+                } else {
+                    byte[] inputArray = ZipUtils.getBufferArray(input);
+                    int inputOffset = ZipUtils.getBufferOffset(input);
+                    if (output.isDirect()) {
+                        long outputAddress = ((DirectBuffer) output).address();
+                        try {
+                            result = deflateBytesBuffer(zsRef.address(),
+                                inputArray, inputOffset + inputPos, inputRem,
+                                outputAddress + outputPos, outputRem,
+                                flush, params);
+                        } finally {
+                            Reference.reachabilityFence(output);
+                        }
+                    } else {
+                        byte[] outputArray = ZipUtils.getBufferArray(output);
+                        int outputOffset = ZipUtils.getBufferOffset(output);
+                        result = deflateBytesBytes(zsRef.address(),
+                            inputArray, inputOffset + inputPos, inputRem,
+                            outputArray, outputOffset + outputPos, outputRem,
+                            flush, params);
+                    }
+                }
+            }
+            int read = (int) (result & 0x7fff_ffffL);
+            int written = (int) (result >>> 31 & 0x7fff_ffffL);
+            if ((result >>> 62 & 1) != 0) {
+                finished = true;
+            }
+            if (params != 0 && (result >>> 63 & 1) == 0) {
+                setParams = false;
+            }
+            if (input != null) {
+                input.position(inputPos + read);
+            } else {
+                this.inputPos = inputPos + read;
+            }
+            output.position(outputPos + written);
+            bytesWritten += written;
+            bytesRead += read;
+            return written;
+        }
     }
 
     /**
@@ -545,7 +881,8 @@
             reset(zsRef.address());
             finish = false;
             finished = false;
-            off = len = 0;
+            input = ZipUtils.defaultBuf;
+            inputArray = null;
             bytesRead = bytesWritten = 0;
         }
     }
@@ -560,7 +897,7 @@
     public void end() {
         synchronized (zsRef) {
             zsRef.clean();
-            buf = null;
+            input = ZipUtils.defaultBuf;
         }
     }
 
@@ -585,11 +922,26 @@
             throw new NullPointerException("Deflater has been closed");
     }
 
-    private static native void initIDs();
     private static native long init(int level, int strategy, boolean nowrap);
-    private static native void setDictionary(long addr, byte[] b, int off, int len);
-    private native int deflateBytes(long addr, byte[] b, int off, int len,
-                                    int flush);
+    private static native void setDictionary(long addr, byte[] b, int off,
+                                             int len);
+    private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
+    private native long deflateBytesBytes(long addr,
+        byte[] inputArray, int inputOff, int inputLen,
+        byte[] outputArray, int outputOff, int outputLen,
+        int flush, int params);
+    private native long deflateBytesBuffer(long addr,
+        byte[] inputArray, int inputOff, int inputLen,
+        long outputAddress, int outputLen,
+        int flush, int params);
+    private native long deflateBufferBytes(long addr,
+        long inputAddress, int inputLen,
+        byte[] outputArray, int outputOff, int outputLen,
+        int flush, int params);
+    private native long deflateBufferBuffer(long addr,
+        long inputAddress, int inputLen,
+        long outputAddress, int outputLen,
+        int flush, int params);
     private static native int getAdler(long addr);
     private static native void reset(long addr);
     private static native void end(long addr);
--- a/src/java.base/share/classes/java/util/zip/Inflater.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/classes/java/util/zip/Inflater.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2018, 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
@@ -26,7 +26,13 @@
 package java.util.zip;
 
 import java.lang.ref.Cleaner.Cleanable;
+import java.lang.ref.Reference;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
+import java.util.Objects;
+
 import jdk.internal.ref.CleanerFactory;
+import sun.nio.ch.DirectBuffer;
 
 /**
  * This class provides support for general purpose decompression using the
@@ -35,8 +41,13 @@
  * protected by patents. It is fully described in the specifications at
  * the <a href="package-summary.html#package.description">java.util.zip
  * package description</a>.
- *
- * <p>The following code fragment demonstrates a trivial compression
+ * <p>
+ * This class inflates sequences of ZLIB compressed bytes. The input byte
+ * sequence is provided in either byte array or byte buffer, via one of the
+ * {@code setInput()} methods. The output byte sequence is written to the
+ * output byte array or byte buffer passed to the {@code deflate()} methods.
+ * <p>
+ * The following code fragment demonstrates a trivial compression
  * and decompression of a string using {@code Deflater} and
  * {@code Inflater}.
  *
@@ -92,14 +103,20 @@
 public class Inflater {
 
     private final InflaterZStreamRef zsRef;
-    private byte[] buf = defaultBuf;
-    private int off, len;
+    private ByteBuffer input = ZipUtils.defaultBuf;
+    private byte[] inputArray;
+    private int inputPos, inputLim;
     private boolean finished;
     private boolean needDict;
     private long bytesRead;
     private long bytesWritten;
 
-    private static final byte[] defaultBuf = new byte[0];
+    /*
+     * These fields are used as an "out" parameter from JNI when a
+     * DataFormatException is thrown during the inflate operation.
+     */
+    private int inputConsumed;
+    private int outputConsumed;
 
     static {
         ZipUtils.loadLibrary();
@@ -129,37 +146,71 @@
     }
 
     /**
-     * Sets input data for decompression. Should be called whenever
-     * needsInput() returns true indicating that more input data is
-     * required.
-     * @param b the input data bytes
+     * Sets input data for decompression.
+     * <p>
+     * One of the {@code setInput()} methods should be called whenever
+     * {@code needsInput()} returns true indicating that more input data
+     * is required.
+     *
+     * @param input the input data bytes
      * @param off the start offset of the input data
      * @param len the length of the input data
      * @see Inflater#needsInput
      */
-    public void setInput(byte[] b, int off, int len) {
-        if (b == null) {
-            throw new NullPointerException();
-        }
-        if (off < 0 || len < 0 || off > b.length - len) {
+    public void setInput(byte[] input, int off, int len) {
+        if (off < 0 || len < 0 || off > input.length - len) {
             throw new ArrayIndexOutOfBoundsException();
         }
         synchronized (zsRef) {
-            this.buf = b;
-            this.off = off;
-            this.len = len;
+            this.input = null;
+            this.inputArray = input;
+            this.inputPos = off;
+            this.inputLim = off + len;
         }
     }
 
     /**
-     * Sets input data for decompression. Should be called whenever
-     * needsInput() returns true indicating that more input data is
-     * required.
-     * @param b the input data bytes
+     * Sets input data for decompression.
+     * <p>
+     * One of the {@code setInput()} methods should be called whenever
+     * {@code needsInput()} returns true indicating that more input data
+     * is required.
+     *
+     * @param input the input data bytes
      * @see Inflater#needsInput
      */
-    public void setInput(byte[] b) {
-        setInput(b, 0, b.length);
+    public void setInput(byte[] input) {
+        setInput(input, 0, input.length);
+    }
+
+    /**
+     * Sets input data for decompression.
+     * <p>
+     * One of the {@code setInput()} methods should be called whenever
+     * {@code needsInput()} returns true indicating that more input data
+     * is required.
+     * <p>
+     * The given buffer's position will be advanced as inflate
+     * operations are performed, up to the buffer's limit.
+     * The input buffer may be modified (refilled) between inflate
+     * operations; doing so is equivalent to creating a new buffer
+     * and setting it with this method.
+     * <p>
+     * Modifying the input buffer's contents, position, or limit
+     * concurrently with an inflate operation will result in
+     * undefined behavior, which may include incorrect operation
+     * results or operation failure.
+     *
+     * @param input the input data bytes
+     * @see Inflater#needsInput
+     * @since 11
+     */
+    public void setInput(ByteBuffer input) {
+        Objects.requireNonNull(input);
+        synchronized (zsRef) {
+            this.input = input;
+            this.inputArray = null;
+        }
     }
 
     /**
@@ -167,22 +218,19 @@
      * called when inflate() returns 0 and needsDictionary() returns true
      * indicating that a preset dictionary is required. The method getAdler()
      * can be used to get the Adler-32 value of the dictionary needed.
-     * @param b the dictionary data bytes
+     * @param dictionary the dictionary data bytes
      * @param off the start offset of the data
      * @param len the length of the data
      * @see Inflater#needsDictionary
      * @see Inflater#getAdler
      */
-    public void setDictionary(byte[] b, int off, int len) {
-        if (b == null) {
-            throw new NullPointerException();
-        }
-        if (off < 0 || len < 0 || off > b.length - len) {
+    public void setDictionary(byte[] dictionary, int off, int len) {
+        if (off < 0 || len < 0 || off > dictionary.length - len) {
             throw new ArrayIndexOutOfBoundsException();
         }
         synchronized (zsRef) {
             ensureOpen();
-            setDictionary(zsRef.address(), b, off, len);
+            setDictionary(zsRef.address(), dictionary, off, len);
             needDict = false;
         }
     }
@@ -192,12 +240,48 @@
      * called when inflate() returns 0 and needsDictionary() returns true
      * indicating that a preset dictionary is required. The method getAdler()
      * can be used to get the Adler-32 value of the dictionary needed.
-     * @param b the dictionary data bytes
+     * @param dictionary the dictionary data bytes
      * @see Inflater#needsDictionary
      * @see Inflater#getAdler
      */
-    public void setDictionary(byte[] b) {
-        setDictionary(b, 0, b.length);
+    public void setDictionary(byte[] dictionary) {
+        setDictionary(dictionary, 0, dictionary.length);
+    }
+
+    /**
+     * Sets the preset dictionary to the bytes in the given buffer. Should be
+     * called when inflate() returns 0 and needsDictionary() returns true
+     * indicating that a preset dictionary is required. The method getAdler()
+     * can be used to get the Adler-32 value of the dictionary needed.
+     * <p>
+     * The bytes in given byte buffer will be fully consumed by this method.  On
+     * return, its position will equal its limit.
+     *
+     * @param dictionary the dictionary data bytes
+     * @see Inflater#needsDictionary
+     * @see Inflater#getAdler
+     * @since 11
+     */
+    public void setDictionary(ByteBuffer dictionary) {
+        synchronized (zsRef) {
+            int position = dictionary.position();
+            int remaining = Math.max(dictionary.limit() - position, 0);
+            ensureOpen();
+            if (dictionary.isDirect()) {
+                long address = ((DirectBuffer) dictionary).address();
+                try {
+                    setDictionaryBuffer(zsRef.address(), address + position, remaining);
+                } finally {
+                    Reference.reachabilityFence(dictionary);
+                }
+            } else {
+                byte[] array = ZipUtils.getBufferArray(dictionary);
+                int offset = ZipUtils.getBufferOffset(dictionary);
+                setDictionary(zsRef.address(), array, offset + position, remaining);
+            }
+            dictionary.position(position + remaining);
+            needDict = false;
+        }
     }
 
     /**
@@ -208,19 +292,22 @@
      */
     public int getRemaining() {
         synchronized (zsRef) {
-            return len;
+            ByteBuffer input = this.input;
+            return input == null ? inputLim - inputPos : input.remaining();
         }
     }
 
     /**
      * Returns true if no data remains in the input buffer. This can
-     * be used to determine if #setInput should be called in order
-     * to provide more input.
+     * be used to determine if one of the {@code setInput()} methods should be
+     * called in order to provide more input.
+     *
      * @return true if no data remains in the input buffer
      */
     public boolean needsInput() {
         synchronized (zsRef) {
-            return len <= 0;
+            ByteBuffer input = this.input;
+            return input == null ? inputLim == inputPos : ! input.hasRemaining();
         }
     }
 
@@ -254,30 +341,103 @@
      * determine if more input data or a preset dictionary is required.
      * In the latter case, getAdler() can be used to get the Adler-32
      * value of the dictionary required.
-     * @param b the buffer for the uncompressed data
+     * <p>
+     * If the {@link #setInput(ByteBuffer)} method was called to provide a buffer
+     * for input, the input buffer's position will be advanced by the number of bytes
+     * consumed by this operation, even in the event that a {@link DataFormatException}
+     * is thrown.
+     * <p>
+     * The {@linkplain #getRemaining() remaining byte count} will be reduced by
+     * the number of consumed input bytes.  If the {@link #setInput(ByteBuffer)}
+     * method was called to provide a buffer for input, the input buffer's position
+     * will be advanced the number of consumed bytes.
+     * <p>
+     * These byte totals, as well as
+     * the {@linkplain #getBytesRead() total bytes read}
+     * and the {@linkplain #getBytesWritten() total bytes written}
+     * values, will be updated even in the event that a {@link DataFormatException}
+     * is thrown to reflect the amount of data consumed and produced before the
+     * exception occurred.
+     *
+     * @param output the buffer for the uncompressed data
      * @param off the start offset of the data
      * @param len the maximum number of uncompressed bytes
      * @return the actual number of uncompressed bytes
-     * @exception DataFormatException if the compressed data format is invalid
+     * @throws DataFormatException if the compressed data format is invalid
      * @see Inflater#needsInput
      * @see Inflater#needsDictionary
      */
-    public int inflate(byte[] b, int off, int len)
+    public int inflate(byte[] output, int off, int len)
         throws DataFormatException
     {
-        if (b == null) {
-            throw new NullPointerException();
-        }
-        if (off < 0 || len < 0 || off > b.length - len) {
+        if (off < 0 || len < 0 || off > output.length - len) {
             throw new ArrayIndexOutOfBoundsException();
         }
         synchronized (zsRef) {
             ensureOpen();
-            int thisLen = this.len;
-            int n = inflateBytes(zsRef.address(), b, off, len);
-            bytesWritten += n;
-            bytesRead += (thisLen - this.len);
-            return n;
+            ByteBuffer input = this.input;
+            long result;
+            int inputPos;
+            try {
+                if (input == null) {
+                    inputPos = this.inputPos;
+                    try {
+                        result = inflateBytesBytes(zsRef.address(),
+                            inputArray, inputPos, inputLim - inputPos,
+                            output, off, len);
+                    } catch (DataFormatException e) {
+                        this.inputPos = inputPos + inputConsumed;
+                        throw e;
+                    }
+                } else {
+                    inputPos = input.position();
+                    try {
+                        int inputRem = Math.max(input.limit() - inputPos, 0);
+                        if (input.isDirect()) {
+                            try {
+                                long inputAddress = ((DirectBuffer) input).address();
+                                result = inflateBufferBytes(zsRef.address(),
+                                    inputAddress + inputPos, inputRem,
+                                    output, off, len);
+                            } finally {
+                                Reference.reachabilityFence(input);
+                            }
+                        } else {
+                            byte[] inputArray = ZipUtils.getBufferArray(input);
+                            int inputOffset = ZipUtils.getBufferOffset(input);
+                            result = inflateBytesBytes(zsRef.address(),
+                                inputArray, inputOffset + inputPos, inputRem,
+                                output, off, len);
+                        }
+                    } catch (DataFormatException e) {
+                        input.position(inputPos + inputConsumed);
+                        throw e;
+                    }
+                }
+            } catch (DataFormatException e) {
+                bytesRead += inputConsumed;
+                inputConsumed = 0;
+                int written = outputConsumed;
+                bytesWritten += written;
+                outputConsumed = 0;
+                throw e;
+            }
+            int read = (int) (result & 0x7fff_ffffL);
+            int written = (int) (result >>> 31 & 0x7fff_ffffL);
+            if ((result >>> 62 & 1) != 0) {
+                finished = true;
+            }
+            if ((result >>> 63 & 1) != 0) {
+                needDict = true;
+            }
+            if (input != null) {
+                input.position(inputPos + read);
+            } else {
+                this.inputPos = inputPos + read;
+            }
+            bytesWritten += written;
+            bytesRead += read;
+            return written;
         }
     }
 
@@ -288,14 +448,177 @@
      * determine if more input data or a preset dictionary is required.
      * In the latter case, getAdler() can be used to get the Adler-32
      * value of the dictionary required.
-     * @param b the buffer for the uncompressed data
+     * <p>
+     * The {@linkplain #getRemaining() remaining byte count} will be reduced by
+     * the number of consumed input bytes.  If the {@link #setInput(ByteBuffer)}
+     * method was called to provide a buffer for input, the input buffer's position
+     * will be advanced the number of consumed bytes.
+     * <p>
+     * These byte totals, as well as
+     * the {@linkplain #getBytesRead() total bytes read}
+     * and the {@linkplain #getBytesWritten() total bytes written}
+     * values, will be updated even in the event that a {@link DataFormatException}
+     * is thrown to reflect the amount of data consumed and produced before the
+     * exception occurred.
+     *
+     * @param output the buffer for the uncompressed data
      * @return the actual number of uncompressed bytes
-     * @exception DataFormatException if the compressed data format is invalid
+     * @throws DataFormatException if the compressed data format is invalid
      * @see Inflater#needsInput
      * @see Inflater#needsDictionary
      */
-    public int inflate(byte[] b) throws DataFormatException {
-        return inflate(b, 0, b.length);
+    public int inflate(byte[] output) throws DataFormatException {
+        return inflate(output, 0, output.length);
+    }
+
+    /**
+     * Uncompresses bytes into specified buffer. Returns actual number
+     * of bytes uncompressed. A return value of 0 indicates that
+     * needsInput() or needsDictionary() should be called in order to
+     * determine if more input data or a preset dictionary is required.
+     * In the latter case, getAdler() can be used to get the Adler-32
+     * value of the dictionary required.
+     * <p>
+     * On success, the position of the given {@code output} byte buffer will be
+     * advanced by as many bytes as were produced by the operation, which is equal
+     * to the number returned by this method.  Note that the position of the
+     * {@code output} buffer will be advanced even in the event that a
+     * {@link DataFormatException} is thrown.
+     * <p>
+     * The {@linkplain #getRemaining() remaining byte count} will be reduced by
+     * the number of consumed input bytes.  If the {@link #setInput(ByteBuffer)}
+     * method was called to provide a buffer for input, the input buffer's position
+     * will be advanced the number of consumed bytes.
+     * <p>
+     * These byte totals, as well as
+     * the {@linkplain #getBytesRead() total bytes read}
+     * and the {@linkplain #getBytesWritten() total bytes written}
+     * values, will be updated even in the event that a {@link DataFormatException}
+     * is thrown to reflect the amount of data consumed and produced before the
+     * exception occurred.
+     *
+     * @param output the buffer for the uncompressed data
+     * @return the actual number of uncompressed bytes
+     * @throws DataFormatException if the compressed data format is invalid
+     * @throws ReadOnlyBufferException if the given output buffer is read-only
+     * @see Inflater#needsInput
+     * @see Inflater#needsDictionary
+     * @since 11
+     */
+    public int inflate(ByteBuffer output) throws DataFormatException {
+        if (output.isReadOnly()) {
+            throw new ReadOnlyBufferException();
+        }
+        synchronized (zsRef) {
+            ensureOpen();
+            ByteBuffer input = this.input;
+            long result;
+            int inputPos;
+            int outputPos = output.position();
+            int outputRem = Math.max(output.limit() - outputPos, 0);
+            try {
+                if (input == null) {
+                    inputPos = this.inputPos;
+                    try {
+                        if (output.isDirect()) {
+                            long outputAddress = ((DirectBuffer) output).address();
+                            try {
+                                result = inflateBytesBuffer(zsRef.address(),
+                                    inputArray, inputPos, inputLim - inputPos,
+                                    outputAddress + outputPos, outputRem);
+                            } finally {
+                                Reference.reachabilityFence(output);
+                            }
+                        } else {
+                            byte[] outputArray = ZipUtils.getBufferArray(output);
+                            int outputOffset = ZipUtils.getBufferOffset(output);
+                            result = inflateBytesBytes(zsRef.address(),
+                                inputArray, inputPos, inputLim - inputPos,
+                                outputArray, outputOffset + outputPos, outputRem);
+                        }
+                    } catch (DataFormatException e) {
+                        this.inputPos = inputPos + inputConsumed;
+                        throw e;
+                    }
+                } else {
+                    inputPos = input.position();
+                    int inputRem = Math.max(input.limit() - inputPos, 0);
+                    try {
+                        if (input.isDirect()) {
+                            long inputAddress = ((DirectBuffer) input).address();
+                            try {
+                                if (output.isDirect()) {
+                                    long outputAddress = ((DirectBuffer) output).address();
+                                    try {
+                                        result = inflateBufferBuffer(zsRef.address(),
+                                            inputAddress + inputPos, inputRem,
+                                            outputAddress + outputPos, outputRem);
+                                    } finally {
+                                        Reference.reachabilityFence(output);
+                                    }
+                                } else {
+                                    byte[] outputArray = ZipUtils.getBufferArray(output);
+                                    int outputOffset = ZipUtils.getBufferOffset(output);
+                                    result = inflateBufferBytes(zsRef.address(),
+                                        inputAddress + inputPos, inputRem,
+                                        outputArray, outputOffset + outputPos, outputRem);
+                                }
+                            } finally {
+                                Reference.reachabilityFence(input);
+                            }
+                        } else {
+                            byte[] inputArray = ZipUtils.getBufferArray(input);
+                            int inputOffset = ZipUtils.getBufferOffset(input);
+                            if (output.isDirect()) {
+                                long outputAddress = ((DirectBuffer) output).address();
+                                try {
+                                    result = inflateBytesBuffer(zsRef.address(),
+                                        inputArray, inputOffset + inputPos, inputRem,
+                                        outputAddress + outputPos, outputRem);
+                                } finally {
+                                    Reference.reachabilityFence(output);
+                                }
+                            } else {
+                                byte[] outputArray = ZipUtils.getBufferArray(output);
+                                int outputOffset = ZipUtils.getBufferOffset(output);
+                                result = inflateBytesBytes(zsRef.address(),
+                                    inputArray, inputOffset + inputPos, inputRem,
+                                    outputArray, outputOffset + outputPos, outputRem);
+                            }
+                        }
+                    } catch (DataFormatException e) {
+                        input.position(inputPos + inputConsumed);
+                        throw e;
+                    }
+                }
+            } catch (DataFormatException e) {
+                bytesRead += inputConsumed;
+                inputConsumed = 0;
+                int written = outputConsumed;
+                output.position(outputPos + written);
+                bytesWritten += written;
+                outputConsumed = 0;
+                throw e;
+            }
+            int read = (int) (result & 0x7fff_ffffL);
+            int written = (int) (result >>> 31 & 0x7fff_ffffL);
+            if ((result >>> 62 & 1) != 0) {
+                finished = true;
+            }
+            if ((result >>> 63 & 1) != 0) {
+                needDict = true;
+            }
+            if (input != null) {
+                input.position(inputPos + read);
+            } else {
+                this.inputPos = inputPos + read;
+            }
+            // Note: this method call also serves to keep the byteBuffer ref alive
+            output.position(outputPos + written);
+            bytesWritten += written;
+            bytesRead += read;
+            return written;
+        }
     }
 
     /**
@@ -368,10 +691,10 @@
         synchronized (zsRef) {
             ensureOpen();
             reset(zsRef.address());
-            buf = defaultBuf;
+            input = ZipUtils.defaultBuf;
+            inputArray = null;
             finished = false;
             needDict = false;
-            off = len = 0;
             bytesRead = bytesWritten = 0;
         }
     }
@@ -386,7 +709,8 @@
     public void end() {
         synchronized (zsRef) {
             zsRef.clean();
-            buf = null;
+            input = ZipUtils.defaultBuf;
+            inputArray = null;
         }
     }
 
@@ -416,18 +740,23 @@
             throw new NullPointerException("Inflater has been closed");
     }
 
-    boolean ended() {
-        synchronized (zsRef) {
-            return zsRef.address() == 0;
-        }
-    }
-
     private static native void initIDs();
     private static native long init(boolean nowrap);
     private static native void setDictionary(long addr, byte[] b, int off,
                                              int len);
-    private native int inflateBytes(long addr, byte[] b, int off, int len)
-            throws DataFormatException;
+    private static native void setDictionaryBuffer(long addr, long bufAddress, int len);
+    private native long inflateBytesBytes(long addr,
+        byte[] inputArray, int inputOff, int inputLen,
+        byte[] outputArray, int outputOff, int outputLen) throws DataFormatException;
+    private native long inflateBytesBuffer(long addr,
+        byte[] inputArray, int inputOff, int inputLen,
+        long outputAddress, int outputLen) throws DataFormatException;
+    private native long inflateBufferBytes(long addr,
+        long inputAddress, int inputLen,
+        byte[] outputArray, int outputOff, int outputLen) throws DataFormatException;
+    private native long inflateBufferBuffer(long addr,
+        long inputAddress, int inputLen,
+        long outputAddress, int outputLen) throws DataFormatException;
     private static native int getAdler(long addr);
     private static native void reset(long addr);
     private static native void end(long addr);
--- a/src/java.base/share/classes/java/util/zip/ZipUtils.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -25,6 +25,8 @@
 
 package java.util.zip;
 
+import java.nio.Buffer;
+import java.nio.ByteBuffer;
 import java.nio.file.attribute.FileTime;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -37,6 +39,9 @@
 
 import static java.util.zip.ZipConstants.ENDHDR;
 
+import jdk.internal.misc.Unsafe;
+import sun.nio.ch.DirectBuffer;
+
 class ZipUtils {
 
     // used to adjust values between Windows and java epoch
@@ -45,6 +50,9 @@
     // used to indicate the corresponding windows time is not available
     public static final long WINDOWS_TIME_NOT_AVAILABLE = Long.MIN_VALUE;
 
+    // static final ByteBuffer defaultBuf = ByteBuffer.allocateDirect(0);
+    static final ByteBuffer defaultBuf = ByteBuffer.allocate(0);
+
     /**
      * Converts Windows time (in microseconds, UTC/GMT) time to FileTime.
      */
@@ -281,4 +289,17 @@
             AccessController.doPrivileged(pa);
         }
     }
+
+    private static final Unsafe unsafe = Unsafe.getUnsafe();
+
+    private static final long byteBufferArrayOffset = unsafe.objectFieldOffset(ByteBuffer.class, "hb");
+    private static final long byteBufferOffsetOffset = unsafe.objectFieldOffset(ByteBuffer.class, "offset");
+
+    static byte[] getBufferArray(ByteBuffer byteBuffer) {
+        return (byte[]) unsafe.getObject(byteBuffer, byteBufferArrayOffset);
+    }
+
+    static int getBufferOffset(ByteBuffer byteBuffer) {
+        return unsafe.getInt(byteBuffer, byteBufferOffsetOffset);
+    }
 }
--- a/src/java.base/share/native/launcher/main.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/launcher/main.c	Mon Apr 23 12:32:25 2018 +0200
@@ -93,7 +93,7 @@
     __initenv = _environ;
 
 #else /* JAVAW */
-JNIEXPORT int JNICALL
+JNIEXPORT int
 main(int argc, char **argv)
 {
     int margc;
--- a/src/java.base/share/native/libjimage/jimage.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libjimage/jimage.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -55,7 +55,7 @@
  *   }
  *   ...
  */
-extern "C" JNIEXPORT JImageFile* JNICALL
+extern "C" JNIEXPORT JImageFile*
 JIMAGE_Open(const char *name, jint* error) {
     // TODO - return a meaningful error code
     *error = 0;
@@ -72,7 +72,7 @@
  * Ex.
  *  (*JImageClose)(image);
  */
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
 JIMAGE_Close(JImageFile* image) {
     ImageFileReader::close((ImageFileReader*) image);
 }
@@ -89,7 +89,7 @@
  *  tty->print_cr(package);
  *  -> java.base
  */
-extern "C" JNIEXPORT const char* JNICALL
+extern "C" JNIEXPORT const char*
 JIMAGE_PackageToModule(JImageFile* image, const char* package_name) {
     return ((ImageFileReader*) image)->get_image_module_data()->package_to_module(package_name);
 }
@@ -108,7 +108,7 @@
  *   JImageLocationRef location = (*JImageFindResource)(image,
  *                                 "java.base", "9.0", "java/lang/String.class", &size);
  */
-extern "C" JNIEXPORT JImageLocationRef JNICALL
+extern "C" JNIEXPORT JImageLocationRef
 JIMAGE_FindResource(JImageFile* image,
         const char* module_name, const char* version, const char* name,
         jlong* size) {
@@ -155,7 +155,7 @@
  *  char* buffer = new char[size];
  *  (*JImageGetResource)(image, location, buffer, size);
  */
-extern "C" JNIEXPORT jlong JNICALL
+extern "C" JNIEXPORT jlong
 JIMAGE_GetResource(JImageFile* image, JImageLocationRef location,
         char* buffer, jlong size) {
     ((ImageFileReader*) image)->get_resource((u4) location, (u1*) buffer);
@@ -184,7 +184,7 @@
  *   }
  *   (*JImageResourceIterator)(image, ctw_visitor, loader);
  */
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
 JIMAGE_ResourceIterator(JImageFile* image,
         JImageResourceVisitor_t visitor, void* arg) {
     ImageFileReader* imageFile = (ImageFileReader*) image;
@@ -226,7 +226,7 @@
  *   char path[JIMAGE_MAX_PATH];
  *    (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH);
  */
-extern "C" JNIEXPORT bool JNICALL
+extern "C" JNIEXPORT bool
 JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef,
                                     char* path, size_t max) {
     ImageFileReader* imageFile = (ImageFileReader*) image;
--- a/src/java.base/share/native/libjimage/jimage.hpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libjimage/jimage.hpp	Mon Apr 23 12:32:25 2018 +0200
@@ -72,7 +72,7 @@
  *   ...
  */
 
-extern "C" JNIEXPORT JImageFile* JNICALL
+extern "C" JNIEXPORT JImageFile*
 JIMAGE_Open(const char *name, jint* error);
 
 typedef JImageFile* (*JImageOpen_t)(const char *name, jint* error);
@@ -87,7 +87,7 @@
  *  (*JImageClose)(image);
  */
 
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
 JIMAGE_Close(JImageFile* jimage);
 
 typedef void (*JImageClose_t)(JImageFile* jimage);
@@ -106,7 +106,7 @@
  *  -> java.base
  */
 
-extern "C" JNIEXPORT const char * JNICALL
+extern "C" JNIEXPORT const char *
 JIMAGE_PackageToModule(JImageFile* jimage, const char* package_name);
 
 typedef const char* (*JImagePackageToModule_t)(JImageFile* jimage, const char* package_name);
@@ -150,7 +150,7 @@
  *  char* buffer = new char[size];
  *  (*JImageGetResource)(image, location, buffer, size);
  */
-extern "C" JNIEXPORT jlong JNICALL
+extern "C" JNIEXPORT jlong
 JIMAGE_GetResource(JImageFile* jimage, JImageLocationRef location,
         char* buffer, jlong size);
 
@@ -185,7 +185,7 @@
         const char* module_name, const char* version, const char* package,
         const char* name, const char* extension, void* arg);
 
-extern "C" JNIEXPORT void JNICALL
+extern "C" JNIEXPORT void
 JIMAGE_ResourceIterator(JImageFile* jimage,
         JImageResourceVisitor_t visitor, void *arg);
 
@@ -202,7 +202,7 @@
  *   char path[JIMAGE_MAX_PATH];
  *    (*JImageResourcePath)(image, location, path, JIMAGE_MAX_PATH);
  */
-extern "C" JNIEXPORT bool JNICALL
+extern "C" JNIEXPORT bool
 JIMAGE_ResourcePath(JImageFile* image, JImageLocationRef locationRef,
                                     char* path, size_t max);
 
--- a/src/java.base/share/native/libzip/CRC32.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libzip/CRC32.c	Mon Apr 23 12:32:25 2018 +0200
@@ -54,7 +54,7 @@
     return crc;
 }
 
-JNIEXPORT jint JNICALL
+JNIEXPORT jint
 ZIP_CRC32(jint crc, const jbyte *buf, jint len)
 {
     return crc32(crc, (Bytef*)buf, len);
--- a/src/java.base/share/native/libzip/Deflater.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libzip/Deflater.c	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -38,34 +38,6 @@
 
 #define DEF_MEM_LEVEL 8
 
-static jfieldID levelID;
-static jfieldID strategyID;
-static jfieldID setParamsID;
-static jfieldID finishID;
-static jfieldID finishedID;
-static jfieldID bufID, offID, lenID;
-
-JNIEXPORT void JNICALL
-Java_java_util_zip_Deflater_initIDs(JNIEnv *env, jclass cls)
-{
-    levelID = (*env)->GetFieldID(env, cls, "level", "I");
-    CHECK_NULL(levelID);
-    strategyID = (*env)->GetFieldID(env, cls, "strategy", "I");
-    CHECK_NULL(strategyID);
-    setParamsID = (*env)->GetFieldID(env, cls, "setParams", "Z");
-    CHECK_NULL(setParamsID);
-    finishID = (*env)->GetFieldID(env, cls, "finish", "Z");
-    CHECK_NULL(finishID);
-    finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
-    CHECK_NULL(finishedID);
-    bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
-    CHECK_NULL(bufID);
-    offID = (*env)->GetFieldID(env, cls, "off", "I");
-    CHECK_NULL(offID);
-    lenID = (*env)->GetFieldID(env, cls, "len", "I");
-    CHECK_NULL(lenID);
-}
-
 JNIEXPORT jlong JNICALL
 Java_java_util_zip_Deflater_init(JNIEnv *env, jclass cls, jint level,
                                  jint strategy, jboolean nowrap)
@@ -104,17 +76,9 @@
     }
 }
 
-JNIEXPORT void JNICALL
-Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
-                                          jarray b, jint off, jint len)
+static void doSetDictionary(JNIEnv *env, jlong addr, jbyte *buf, jint len)
 {
-    Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
-    int res;
-    if (buf == 0) {/* out of memory */
-        return;
-    }
-    res = deflateSetDictionary((z_stream *)jlong_to_ptr(addr), buf + off, len);
-    (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+    int res = deflateSetDictionary(jlong_to_ptr(addr), (Bytef *) buf, len);
     switch (res) {
     case Z_OK:
         break;
@@ -127,94 +91,173 @@
     }
 }
 
-JNIEXPORT jint JNICALL
-Java_java_util_zip_Deflater_deflateBytes(JNIEnv *env, jobject this, jlong addr,
-                                         jarray b, jint off, jint len, jint flush)
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
+                                          jbyteArray b, jint off, jint len)
+{
+    jbyte *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+    if (buf == NULL) /* out of memory */
+        return;
+    doSetDictionary(env, addr, buf + off, len);
+    (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Deflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr,
+                                          jlong bufferAddr, jint len)
+{
+    jbyte *buf = jlong_to_ptr(bufferAddr);
+    doSetDictionary(env, addr, buf, len);
+}
+
+static jlong doDeflate(JNIEnv *env, jobject this, jlong addr,
+                       jbyte *input, jint inputLen,
+                       jbyte *output, jint outputLen,
+                       jint flush, jint params)
 {
     z_stream *strm = jlong_to_ptr(addr);
+    jint inputUsed = 0, outputUsed = 0;
+    int finished = 0;
+    int setParams = params & 1;
 
-    jarray this_buf = (*env)->GetObjectField(env, this, bufID);
-    jint this_off = (*env)->GetIntField(env, this, offID);
-    jint this_len = (*env)->GetIntField(env, this, lenID);
-    jbyte *in_buf;
-    jbyte *out_buf;
-    int res;
-    if ((*env)->GetBooleanField(env, this, setParamsID)) {
-        int level = (*env)->GetIntField(env, this, levelID);
-        int strategy = (*env)->GetIntField(env, this, strategyID);
-        in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
-        if (in_buf == NULL) {
-            // Throw OOME only when length is not zero
-            if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL)
-                JNU_ThrowOutOfMemoryError(env, 0);
-            return 0;
-        }
-        out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
-        if (out_buf == NULL) {
-            (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
-            if (len != 0 && (*env)->ExceptionOccurred(env) == NULL)
-                JNU_ThrowOutOfMemoryError(env, 0);
-            return 0;
-        }
+    strm->next_in  = (Bytef *) input;
+    strm->next_out = (Bytef *) output;
+    strm->avail_in  = inputLen;
+    strm->avail_out = outputLen;
 
-        strm->next_in = (Bytef *) (in_buf + this_off);
-        strm->next_out = (Bytef *) (out_buf + off);
-        strm->avail_in = this_len;
-        strm->avail_out = len;
-        res = deflateParams(strm, level, strategy);
-        (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
-        (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+    if (setParams) {
+        int strategy = (params >> 1) & 3;
+        int level = params >> 3;
+        int res = deflateParams(strm, level, strategy);
         switch (res) {
         case Z_OK:
-            (*env)->SetBooleanField(env, this, setParamsID, JNI_FALSE);
+            setParams = 0;
+            /* fall through */
         case Z_BUF_ERROR:
-            this_off += this_len - strm->avail_in;
-            (*env)->SetIntField(env, this, offID, this_off);
-            (*env)->SetIntField(env, this, lenID, strm->avail_in);
-            return (jint) (len - strm->avail_out);
+            inputUsed = inputLen - strm->avail_in;
+            outputUsed = outputLen - strm->avail_out;
+            break;
         default:
             JNU_ThrowInternalError(env, strm->msg);
             return 0;
         }
     } else {
-        jboolean finish = (*env)->GetBooleanField(env, this, finishID);
-        in_buf = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
-        if (in_buf == NULL) {
-            if (this_len != 0)
-                JNU_ThrowOutOfMemoryError(env, 0);
-            return 0;
-        }
-        out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
-        if (out_buf == NULL) {
-            (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
-            if (len != 0)
-                JNU_ThrowOutOfMemoryError(env, 0);
-
-            return 0;
-        }
-
-        strm->next_in = (Bytef *) (in_buf + this_off);
-        strm->next_out = (Bytef *) (out_buf + off);
-        strm->avail_in = this_len;
-        strm->avail_out = len;
-        res = deflate(strm, finish ? Z_FINISH : flush);
-        (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
-        (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
+        int res = deflate(strm, flush);
         switch (res) {
         case Z_STREAM_END:
-            (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
+            finished = 1;
             /* fall through */
         case Z_OK:
         case Z_BUF_ERROR:
-            this_off += this_len - strm->avail_in;
-            (*env)->SetIntField(env, this, offID, this_off);
-            (*env)->SetIntField(env, this, lenID, strm->avail_in);
-            return len - strm->avail_out;
+            inputUsed = inputLen - strm->avail_in;
+            outputUsed = outputLen - strm->avail_out;
+            break;
         default:
             JNU_ThrowInternalError(env, strm->msg);
             return 0;
         }
     }
+    return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)setParams) << 63);
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBytesBytes(JNIEnv *env, jobject this, jlong addr,
+                                         jbyteArray inputArray, jint inputOff, jint inputLen,
+                                         jbyteArray outputArray, jint outputOff, jint outputLen,
+                                         jint flush, jint params)
+{
+    jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+    jbyte *output;
+    jlong retVal;
+    if (input == NULL) {
+        if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+    output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+    if (output == NULL) {
+        (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+        if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+
+    retVal = doDeflate(env, this, addr,
+            input + inputOff, inputLen,
+            output + outputOff, outputLen,
+            flush, params);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+    return retVal;
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBytesBuffer(JNIEnv *env, jobject this, jlong addr,
+                                         jbyteArray inputArray, jint inputOff, jint inputLen,
+                                         jlong outputBuffer, jint outputLen,
+                                         jint flush, jint params)
+{
+    jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+    jbyte *output;
+    jlong retVal;
+    if (input == NULL) {
+        if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+    output = jlong_to_ptr(outputBuffer);
+
+    retVal = doDeflate(env, this, addr,
+            input + inputOff, inputLen,
+            output, outputLen,
+            flush, params);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+    return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBufferBytes(JNIEnv *env, jobject this, jlong addr,
+                                         jlong inputBuffer, jint inputLen,
+                                         jbyteArray outputArray, jint outputOff, jint outputLen,
+                                         jint flush, jint params)
+{
+    jbyte *input = jlong_to_ptr(inputBuffer);
+    jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+    jlong retVal;
+    if (output == NULL) {
+        if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+
+    retVal = doDeflate(env, this, addr,
+            input, inputLen,
+            output + outputOff, outputLen,
+            flush, params);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, outputArray, input, 0);
+
+    return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Deflater_deflateBufferBuffer(JNIEnv *env, jobject this, jlong addr,
+                                         jlong inputBuffer, jint inputLen,
+                                         jlong outputBuffer, jint outputLen,
+                                         jint flush, jint params)
+{
+    jbyte *input = jlong_to_ptr(inputBuffer);
+    jbyte *output = jlong_to_ptr(outputBuffer);
+
+    return doDeflate(env, this, addr,
+            input, inputLen,
+            output, outputLen,
+            flush, params);
 }
 
 JNIEXPORT jint JNICALL
--- a/src/java.base/share/native/libzip/Inflater.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libzip/Inflater.c	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2018, 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
@@ -42,23 +42,16 @@
 #define ThrowDataFormatException(env, msg) \
         JNU_ThrowByName(env, "java/util/zip/DataFormatException", msg)
 
-static jfieldID needDictID;
-static jfieldID finishedID;
-static jfieldID bufID, offID, lenID;
+static jfieldID inputConsumedID;
+static jfieldID outputConsumedID;
 
 JNIEXPORT void JNICALL
 Java_java_util_zip_Inflater_initIDs(JNIEnv *env, jclass cls)
 {
-    needDictID = (*env)->GetFieldID(env, cls, "needDict", "Z");
-    CHECK_NULL(needDictID);
-    finishedID = (*env)->GetFieldID(env, cls, "finished", "Z");
-    CHECK_NULL(finishedID);
-    bufID = (*env)->GetFieldID(env, cls, "buf", "[B");
-    CHECK_NULL(bufID);
-    offID = (*env)->GetFieldID(env, cls, "off", "I");
-    CHECK_NULL(offID);
-    lenID = (*env)->GetFieldID(env, cls, "len", "I");
-    CHECK_NULL(lenID);
+    inputConsumedID = (*env)->GetFieldID(env, cls, "inputConsumed", "I");
+    outputConsumedID = (*env)->GetFieldID(env, cls, "outputConsumed", "I");
+    CHECK_NULL(inputConsumedID);
+    CHECK_NULL(outputConsumedID);
 }
 
 JNIEXPORT jlong JNICALL
@@ -94,16 +87,9 @@
     }
 }
 
-JNIEXPORT void JNICALL
-Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
-                                          jarray b, jint off, jint len)
+static void doSetDictionary(JNIEnv *env, jlong addr, jbyte *buf, jint len)
 {
-    Bytef *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
-    int res;
-    if (buf == 0) /* out of memory */
-        return;
-    res = inflateSetDictionary(jlong_to_ptr(addr), buf + off, len);
-    (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+    int res = inflateSetDictionary(jlong_to_ptr(addr), (Bytef *) buf, len);
     switch (res) {
     case Z_OK:
         break;
@@ -117,68 +103,168 @@
     }
 }
 
-JNIEXPORT jint JNICALL
-Java_java_util_zip_Inflater_inflateBytes(JNIEnv *env, jobject this, jlong addr,
-                                         jarray b, jint off, jint len)
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_setDictionary(JNIEnv *env, jclass cls, jlong addr,
+                                          jbyteArray b, jint off, jint len)
+{
+    jbyte *buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
+    if (buf == NULL) /* out of memory */
+        return;
+    doSetDictionary(env, addr, buf + off, len);
+    (*env)->ReleasePrimitiveArrayCritical(env, b, buf, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_java_util_zip_Inflater_setDictionaryBuffer(JNIEnv *env, jclass cls, jlong addr,
+                                          jlong bufferAddr, jint len)
+{
+    jbyte *buf = jlong_to_ptr(bufferAddr);
+    doSetDictionary(env, addr, buf, len);
+}
+
+static jlong doInflate(JNIEnv *env, jobject this, jlong addr,
+                       jbyte *input, jint inputLen,
+                       jbyte *output, jint outputLen)
 {
     z_stream *strm = jlong_to_ptr(addr);
-    jarray this_buf = (jarray)(*env)->GetObjectField(env, this, bufID);
-    jint this_off = (*env)->GetIntField(env, this, offID);
-    jint this_len = (*env)->GetIntField(env, this, lenID);
-
-    jbyte *in_buf;
-    jbyte *out_buf;
+    jint inputUsed = 0, outputUsed = 0;
+    int finished = 0;
+    int needDict = 0;
     int ret;
 
-    in_buf  = (*env)->GetPrimitiveArrayCritical(env, this_buf, 0);
-    if (in_buf == NULL) {
-        if (this_len != 0 && (*env)->ExceptionOccurred(env) == NULL)
-            JNU_ThrowOutOfMemoryError(env, 0);
-        return 0;
-    }
-    out_buf = (*env)->GetPrimitiveArrayCritical(env, b, 0);
-    if (out_buf == NULL) {
-        (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
-        if (len != 0 && (*env)->ExceptionOccurred(env) == NULL)
-            JNU_ThrowOutOfMemoryError(env, 0);
-        return 0;
-    }
-    strm->next_in  = (Bytef *) (in_buf + this_off);
-    strm->next_out = (Bytef *) (out_buf + off);
-    strm->avail_in  = this_len;
-    strm->avail_out = len;
+    strm->next_in  = (Bytef *) input;
+    strm->next_out = (Bytef *) output;
+    strm->avail_in  = inputLen;
+    strm->avail_out = outputLen;
+
     ret = inflate(strm, Z_PARTIAL_FLUSH);
-    (*env)->ReleasePrimitiveArrayCritical(env, b, out_buf, 0);
-    (*env)->ReleasePrimitiveArrayCritical(env, this_buf, in_buf, 0);
 
     switch (ret) {
     case Z_STREAM_END:
-        (*env)->SetBooleanField(env, this, finishedID, JNI_TRUE);
+        finished = 1;
         /* fall through */
     case Z_OK:
-        this_off += this_len - strm->avail_in;
-        (*env)->SetIntField(env, this, offID, this_off);
-        (*env)->SetIntField(env, this, lenID, strm->avail_in);
-        return (jint) (len - strm->avail_out);
+        inputUsed = inputLen - strm->avail_in;
+        outputUsed = outputLen - strm->avail_out;
+        break;
     case Z_NEED_DICT:
-        (*env)->SetBooleanField(env, this, needDictID, JNI_TRUE);
+        needDict = 1;
         /* Might have consumed some input here! */
-        this_off += this_len - strm->avail_in;
-        (*env)->SetIntField(env, this, offID, this_off);
-        (*env)->SetIntField(env, this, lenID, strm->avail_in);
-        return 0;
+        inputUsed = inputLen - strm->avail_in;
+        /* zlib is unclear about whether output may be produced */
+        outputUsed = outputLen - strm->avail_out;
+        break;
     case Z_BUF_ERROR:
-        return 0;
+        break;
     case Z_DATA_ERROR:
+        inputUsed = inputLen - strm->avail_in;
+        (*env)->SetIntField(env, this, inputConsumedID, inputUsed);
+        outputUsed = outputLen - strm->avail_out;
+        (*env)->SetIntField(env, this, outputConsumedID, outputUsed);
         ThrowDataFormatException(env, strm->msg);
-        return 0;
+        break;
     case Z_MEM_ERROR:
         JNU_ThrowOutOfMemoryError(env, 0);
-        return 0;
+        break;
     default:
         JNU_ThrowInternalError(env, strm->msg);
-        return 0;
+        break;
+    }
+    return ((jlong)inputUsed) | (((jlong)outputUsed) << 31) | (((jlong)finished) << 62) | (((jlong)needDict) << 63);
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBytesBytes(JNIEnv *env, jobject this, jlong addr,
+                                         jbyteArray inputArray, jint inputOff, jint inputLen,
+                                         jbyteArray outputArray, jint outputOff, jint outputLen)
+{
+    jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+    jbyte *output;
+    jlong retVal;
+
+    if (input == NULL) {
+        if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+    output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+    if (output == NULL) {
+        (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+        if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
     }
+
+    retVal = doInflate(env, this, addr,
+            input + inputOff, inputLen,
+            output + outputOff, outputLen);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
+    (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+    return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBytesBuffer(JNIEnv *env, jobject this, jlong addr,
+                                         jbyteArray inputArray, jint inputOff, jint inputLen,
+                                         jlong outputBuffer, jint outputLen)
+{
+    jbyte *input = (*env)->GetPrimitiveArrayCritical(env, inputArray, 0);
+    jbyte *output;
+    jlong retVal;
+
+    if (input == NULL) {
+        if (inputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+    output = jlong_to_ptr(outputBuffer);
+
+    retVal = doInflate(env, this, addr,
+            input + inputOff, inputLen,
+            output, outputLen);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, inputArray, input, 0);
+
+    return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBufferBytes(JNIEnv *env, jobject this, jlong addr,
+                                         jlong inputBuffer, jint inputLen,
+                                         jbyteArray outputArray, jint outputOff, jint outputLen)
+{
+    jbyte *input = jlong_to_ptr(inputBuffer);
+    jbyte *output = (*env)->GetPrimitiveArrayCritical(env, outputArray, 0);
+    jlong retVal;
+
+    if (output == NULL) {
+        if (outputLen != 0 && (*env)->ExceptionOccurred(env) == NULL)
+            JNU_ThrowOutOfMemoryError(env, 0);
+        return 0L;
+    }
+
+    retVal = doInflate(env, this, addr,
+            input, inputLen,
+            output + outputOff, outputLen);
+
+    (*env)->ReleasePrimitiveArrayCritical(env, outputArray, output, 0);
+
+    return retVal;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_util_zip_Inflater_inflateBufferBuffer(JNIEnv *env, jobject this, jlong addr,
+                                         jlong inputBuffer, jint inputLen,
+                                         jlong outputBuffer, jint outputLen)
+{
+    jbyte *input = jlong_to_ptr(inputBuffer);
+    jbyte *output = jlong_to_ptr(outputBuffer);
+
+    return doInflate(env, this, addr,
+            input, inputLen,
+            output, outputLen);
 }
 
 JNIEXPORT jint JNICALL
--- a/src/java.base/share/native/libzip/zip_util.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libzip/zip_util.c	Mon Apr 23 12:32:25 2018 +0200
@@ -881,7 +881,7 @@
  * set to the error message text if msg != 0. Otherwise, *msg will be
  * set to NULL. Caller doesn't need to free the error message.
  */
-JNIEXPORT jzfile * JNICALL
+JNIEXPORT jzfile *
 ZIP_Open(const char *name, char **pmsg)
 {
     jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY, 0);
@@ -895,7 +895,7 @@
 /*
  * Closes the specified zip file object.
  */
-JNIEXPORT void JNICALL
+JNIEXPORT void
 ZIP_Close(jzfile *zip)
 {
     MLOCK(zfiles_lock);
@@ -1115,7 +1115,7 @@
  * Returns the zip entry corresponding to the specified name, or
  * NULL if not found.
  */
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
 ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
 {
     if (ulen == 0) {
@@ -1238,7 +1238,7 @@
  * Returns the n'th (starting at zero) zip file entry, or NULL if the
  * specified index was out of range.
  */
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
 ZIP_GetNextEntry(jzfile *zip, jint n)
 {
     jzentry *result;
@@ -1439,7 +1439,7 @@
  * The current implementation does not support reading an entry that
  * has the size bigger than 2**32 bytes in ONE invocation.
  */
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
 {
     jzentry *entry = ZIP_GetEntry(zip, name, 0);
@@ -1456,7 +1456,7 @@
  * Note: this is called from the separately delivered VM (hotspot/classic)
  * so we have to be careful to maintain the expected behaviour.
  */
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
 {
     char *msg;
@@ -1515,7 +1515,7 @@
     return JNI_TRUE;
 }
 
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
 ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg)
 {
     z_stream strm;
--- a/src/java.base/share/native/libzip/zip_util.h	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/share/native/libzip/zip_util.h	Mon Apr 23 12:32:25 2018 +0200
@@ -241,16 +241,16 @@
  */
 #define ZIP_ENDCHAIN ((jint)-1)
 
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
 ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP);
 
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
 ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entrynm);
 
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
 ZIP_GetNextEntry(jzfile *zip, jint n);
 
-JNIEXPORT jzfile * JNICALL
+JNIEXPORT jzfile *
 ZIP_Open(const char *name, char **pmsg);
 
 jzfile *
@@ -265,10 +265,10 @@
 jzfile *
 ZIP_Put_In_Cache0(const char *name, ZFILE zfd, char **pmsg, jlong lastModified, jboolean usemmap);
 
-JNIEXPORT void JNICALL
+JNIEXPORT void
 ZIP_Close(jzfile *zip);
 
-JNIEXPORT jzentry * JNICALL
+JNIEXPORT jzentry *
 ZIP_GetEntry(jzfile *zip, char *name, jint ulen);
 JNIEXPORT void JNICALL
 ZIP_Lock(jzfile *zip);
@@ -281,7 +281,7 @@
 jlong ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry);
 jzentry * ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash);
 
-JNIEXPORT jboolean JNICALL
+JNIEXPORT jboolean
 ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
 
 #endif /* !_ZIP_H_ */
--- a/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java	Mon Apr 23 12:32:25 2018 +0200
@@ -26,14 +26,18 @@
 
 import java.io.IOException;
 import java.io.FileDescriptor;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import sun.security.action.GetPropertyAction;
 import jdk.internal.misc.SharedSecrets;
 import jdk.internal.misc.JavaIOFileDescriptorAccess;
 
 /**
- * This class defines the plain SocketImpl that is used on Windows platforms
- * greater or equal to Windows Vista. These platforms have a dual
- * layer TCP/IP stack and can handle both IPv4 and IPV6 through a
- * single file descriptor.
+ * This class defines the plain SocketImpl.
+ * When java.net.preferIPv4Stack system property is set to true, it uses
+ * IPv4-only socket.
+ * When java.net.preferIPv4Stack is set to false, it handles both IPv4
+ * and IPv6 through a single file descriptor.
  *
  * @author Chris Hegarty
  */
@@ -43,30 +47,43 @@
     private static final JavaIOFileDescriptorAccess fdAccess =
         SharedSecrets.getJavaIOFileDescriptorAccess();
 
-    // true if this socket is exclusively bound
-    private final boolean exclusiveBind;
+    private static final boolean preferIPv4Stack =
+            Boolean.parseBoolean(AccessController.doPrivileged(
+                new GetPropertyAction("java.net.preferIPv4Stack", "false")));
+
+    /**
+     * Empty value of sun.net.useExclusiveBind is treated as 'true'.
+     */
+    private static final boolean useExclusiveBind;
 
-    // emulates SO_REUSEADDR when exclusiveBind is true
+    static {
+        String exclBindProp = AccessController.doPrivileged(
+                new GetPropertyAction("sun.net.useExclusiveBind", ""));
+        useExclusiveBind = exclBindProp.isEmpty()
+                || Boolean.parseBoolean(exclBindProp);
+    }
+
+    // emulates SO_REUSEADDR when useExclusiveBind is true
     private boolean isReuseAddress;
 
-    public DualStackPlainSocketImpl(boolean exclBind) {
-        exclusiveBind = exclBind;
+    public DualStackPlainSocketImpl() {
     }
 
-    public DualStackPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
+    public DualStackPlainSocketImpl(FileDescriptor fd) {
         this.fd = fd;
-        exclusiveBind = exclBind;
     }
 
+    @Override
     void socketCreate(boolean stream) throws IOException {
         if (fd == null)
             throw new SocketException("Socket closed");
 
-        int newfd = socket0(stream, false /*v6 Only*/);
+        int newfd = socket0(stream);
 
         fdAccess.set(fd, newfd);
     }
 
+    @Override
     void socketConnect(InetAddress address, int port, int timeout)
         throws IOException {
         int nativefd = checkAndReturnNativeFD();
@@ -74,6 +91,9 @@
         if (address == null)
             throw new NullPointerException("inet address argument is null.");
 
+        if (preferIPv4Stack && !(address instanceof Inet4Address))
+            throw new SocketException("Protocol family not supported");
+
         int connectResult;
         if (timeout <= 0) {
             connectResult = connect0(nativefd, address, port);
@@ -97,13 +117,17 @@
             localport = localPort0(nativefd);
     }
 
+    @Override
     void socketBind(InetAddress address, int port) throws IOException {
         int nativefd = checkAndReturnNativeFD();
 
         if (address == null)
             throw new NullPointerException("inet address argument is null.");
 
-        bind0(nativefd, address, port, exclusiveBind);
+        if (preferIPv4Stack && !(address instanceof Inet4Address))
+            throw new SocketException("Protocol family not supported");
+
+        bind0(nativefd, address, port, useExclusiveBind);
         if (port == 0) {
             localport = localPort0(nativefd);
         } else {
@@ -113,12 +137,14 @@
         this.address = address;
     }
 
+    @Override
     void socketListen(int backlog) throws IOException {
         int nativefd = checkAndReturnNativeFD();
 
         listen0(nativefd, backlog);
     }
 
+    @Override
     void socketAccept(SocketImpl s) throws IOException {
         int nativefd = checkAndReturnNativeFD();
 
@@ -148,13 +174,17 @@
         s.port = isa.getPort();
         s.address = isa.getAddress();
         s.localport = localport;
+        if (preferIPv4Stack && !(s.address instanceof Inet4Address))
+            throw new SocketException("Protocol family not supported");
     }
 
+    @Override
     int socketAvailable() throws IOException {
         int nativefd = checkAndReturnNativeFD();
         return available0(nativefd);
     }
 
+    @Override
     void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
         if (fd == null)
             throw new SocketException("Socket closed");
@@ -167,6 +197,7 @@
         close0(nativefd);
     }
 
+    @Override
     void socketShutdown(int howto) throws IOException {
         int nativefd = checkAndReturnNativeFD();
         shutdown0(nativefd, howto);
@@ -174,41 +205,51 @@
 
     // Intentional fallthrough after SO_REUSEADDR
     @SuppressWarnings("fallthrough")
+    @Override
     void socketSetOption(int opt, boolean on, Object value)
         throws SocketException {
-        int nativefd = checkAndReturnNativeFD();
 
-        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 nativefd = checkAndReturnNativeFD();
+
+        if (opt == SO_TIMEOUT) {
+            if (preferIPv4Stack) {
+                // Don't enable the socket option on ServerSocket as it's
+                // meaningless (we don't receive on a ServerSocket).
+                if (serverSocket == null) {
+                    setSoTimeout0(nativefd, ((Integer)value).intValue());
+                }
+            } // else timeout is implemented through select.
+            return;
+        }
+
         int optionValue = 0;
 
         switch(opt) {
-            case SO_REUSEADDR :
-                if (exclusiveBind) {
+            case SO_REUSEADDR:
+                if (useExclusiveBind) {
                     // SO_REUSEADDR emulated when using exclusive bind
                     isReuseAddress = on;
                     return;
                 }
                 // intentional fallthrough
-            case TCP_NODELAY :
-            case SO_OOBINLINE :
-            case SO_KEEPALIVE :
+            case TCP_NODELAY:
+            case SO_OOBINLINE:
+            case SO_KEEPALIVE:
                 optionValue = on ? 1 : 0;
                 break;
-            case SO_SNDBUF :
-            case SO_RCVBUF :
-            case IP_TOS :
+            case SO_SNDBUF:
+            case SO_RCVBUF:
+            case IP_TOS:
                 optionValue = ((Integer)value).intValue();
                 break;
-            case SO_LINGER :
+            case SO_LINGER:
                 if (on) {
-                    optionValue =  ((Integer)value).intValue();
+                    optionValue = ((Integer)value).intValue();
                 } else {
                     optionValue = -1;
                 }
@@ -220,7 +261,15 @@
         setIntOption(nativefd, opt, optionValue);
     }
 
-    int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
+    @Override
+    int socketGetOption(int opt, Object iaContainerObj)
+        throws SocketException {
+
+        // SO_REUSEPORT is not supported on Windows.
+        if (opt == SO_REUSEPORT) {
+            throw new UnsupportedOperationException("unsupported option");
+        }
+
         int nativefd = checkAndReturnNativeFD();
 
         // SO_BINDADDR is not a socket option.
@@ -228,27 +277,24 @@
             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)
-            return isReuseAddress? 1 : -1;
+        if (opt == SO_REUSEADDR && useExclusiveBind)
+            return isReuseAddress ? 1 : -1;
 
         int value = getIntOption(nativefd, opt);
 
         switch (opt) {
-            case TCP_NODELAY :
-            case SO_OOBINLINE :
-            case SO_KEEPALIVE :
-            case SO_REUSEADDR :
+            case TCP_NODELAY:
+            case SO_OOBINLINE:
+            case SO_KEEPALIVE:
+            case SO_REUSEADDR:
                 return (value == 0) ? -1 : 1;
         }
         return value;
     }
 
+    @Override
     void socketSendUrgentData(int data) throws IOException {
         int nativefd = checkAndReturnNativeFD();
         sendOOB(nativefd, data);
@@ -271,7 +317,7 @@
 
     static native void initIDs();
 
-    static native int socket0(boolean stream, boolean v6Only) throws IOException;
+    static native int socket0(boolean stream) throws IOException;
 
     static native void bind0(int fd, InetAddress localAddress, int localport,
                              boolean exclBind)
@@ -300,6 +346,8 @@
 
     static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
 
+    static native void setSoTimeout0(int fd, int timeout) throws SocketException;
+
     static native int getIntOption(int fd, int cmd) throws SocketException;
 
     static native void sendOOB(int fd, int data) throws IOException;
--- a/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/windows/classes/java/net/PlainSocketImpl.java	Mon Apr 23 12:32:25 2018 +0200
@@ -25,20 +25,13 @@
 package java.net;
 
 import java.io.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import sun.security.action.GetPropertyAction;
 
 /*
  * This class PlainSocketImpl simply delegates to the appropriate real
  * SocketImpl. We do this because PlainSocketImpl is already extended
  * by SocksSocketImpl.
  * <p>
- * There are two possibilities for the real SocketImpl,
- * TwoStacksPlainSocketImpl or DualStackPlainSocketImpl. We use
- * DualStackPlainSocketImpl on systems that have a dual stack
- * TCP implementation. Otherwise we create an instance of
- * TwoStacksPlainSocketImpl and delegate to it.
+ * There is one possibility for the real SocketImpl: DualStackPlainSocketImpl.
  *
  * @author Chris Hegarty
  */
@@ -46,44 +39,18 @@
 class PlainSocketImpl extends AbstractPlainSocketImpl {
     private AbstractPlainSocketImpl impl;
 
-    /* java.net.preferIPv4Stack */
-    private static final boolean preferIPv4Stack;
-
-    /* True if exclusive binding is on for Windows */
-    private static final boolean exclusiveBind;
-
-    static {
-        preferIPv4Stack = Boolean.parseBoolean(
-        AccessController.doPrivileged(
-                new GetPropertyAction("java.net.preferIPv4Stack")));
-
-        String exclBindProp = AccessController.doPrivileged(
-                new GetPropertyAction("sun.net.useExclusiveBind", ""));
-        exclusiveBind = (exclBindProp.isEmpty())
-                ? true
-                : Boolean.parseBoolean(exclBindProp);
-    }
-
     /**
      * Constructs an empty instance.
      */
     PlainSocketImpl() {
-        if (!preferIPv4Stack) {
-            impl = new DualStackPlainSocketImpl(exclusiveBind);
-        } else {
-            impl = new TwoStacksPlainSocketImpl(exclusiveBind);
-        }
+        impl = new DualStackPlainSocketImpl();
     }
 
     /**
      * Constructs an instance with the given file descriptor.
      */
     PlainSocketImpl(FileDescriptor fd) {
-        if (!preferIPv4Stack) {
-            impl = new DualStackPlainSocketImpl(fd, exclusiveBind);
-        } else {
-            impl = new TwoStacksPlainSocketImpl(fd, exclusiveBind);
-        }
+        impl = new DualStackPlainSocketImpl(fd);
     }
 
     // Override methods in SocketImpl that access impl's fields.
@@ -148,18 +115,10 @@
     }
 
     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);
     }
 
@@ -271,8 +230,8 @@
 
     // Override methods in AbstractPlainSocketImpl that need to be implemented.
 
-    void socketCreate(boolean isServer) throws IOException {
-        impl.socketCreate(isServer);
+    void socketCreate(boolean stream) throws IOException {
+        impl.socketCreate(stream);
     }
 
     void socketConnect(InetAddress address, int port, int timeout)
@@ -307,18 +266,10 @@
 
     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);
     }
 
--- a/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java	Thu Apr 19 15:37:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) 2007, 2018, 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.
- */
-package java.net;
-
-import java.io.IOException;
-import java.io.FileDescriptor;
-import sun.net.ResourceManager;
-import jdk.internal.misc.SharedSecrets;
-import jdk.internal.misc.JavaIOFileDescriptorAccess;
-
-/*
- * This class defines the plain SocketImpl that is used when
- * the System property java.net.preferIPv4Stack is set to true.
- *
- * @author Chris Hegarty
- */
-
-class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl {
-
-    private static final JavaIOFileDescriptorAccess fdAccess =
-        SharedSecrets.getJavaIOFileDescriptorAccess();
-
-    // true if this socket is exclusively bound
-    private final boolean exclusiveBind;
-
-    // emulates SO_REUSEADDR when exclusiveBind is true
-    private boolean isReuseAddress;
-
-    public TwoStacksPlainSocketImpl(boolean exclBind) {
-        exclusiveBind = exclBind;
-    }
-
-    public TwoStacksPlainSocketImpl(FileDescriptor fd, boolean exclBind) {
-        this.fd = fd;
-        exclusiveBind = exclBind;
-    }
-
-    void socketCreate(boolean stream) throws IOException {
-        if (fd == null)
-            throw new SocketException("Socket closed");
-
-        int newfd = socket0(stream, false /*v6 Only*/);
-
-        fdAccess.set(fd, newfd);
-    }
-
-    @Override
-    void socketConnect(InetAddress address, int port, int timeout)
-        throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (address == null)
-            throw new NullPointerException("inet address argument is null.");
-
-        int connectResult;
-        if (timeout <= 0) {
-            connectResult = connect0(nativefd, address, port);
-        } else {
-            configureBlocking(nativefd, false);
-            try {
-                connectResult = connect0(nativefd, address, port);
-                if (connectResult == WOULDBLOCK) {
-                    waitForConnect(nativefd, timeout);
-                }
-            } finally {
-                configureBlocking(nativefd, true);
-            }
-        }
-        /*
-         * We need to set the local port field. If bind was called
-         * previous to the connect (by the client) then localport field
-         * will already be set.
-         */
-        if (localport == 0)
-            localport = localPort0(nativefd);
-    }
-
-    @Override
-    void socketBind(InetAddress address, int port) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (address == null)
-            throw new NullPointerException("inet address argument is null.");
-
-        bind0(nativefd, address, port, exclusiveBind);
-        if (port == 0) {
-            localport = localPort0(nativefd);
-        } else {
-            localport = port;
-        }
-
-        this.address = address;
-    }
-
-    @Override
-    void socketListen(int backlog) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        listen0(nativefd, backlog);
-    }
-
-    @Override
-    void socketAccept(SocketImpl s) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (s == null)
-            throw new NullPointerException("socket is null");
-
-        int newfd = -1;
-        InetSocketAddress[] isaa = new InetSocketAddress[1];
-        if (timeout <= 0) {
-            newfd = accept0(nativefd, isaa);
-        } else {
-            configureBlocking(nativefd, false);
-            try {
-                waitForNewConnection(nativefd, timeout);
-                newfd = accept0(nativefd, isaa);
-                if (newfd != -1) {
-                    configureBlocking(newfd, true);
-                }
-            } finally {
-                configureBlocking(nativefd, true);
-            }
-        }
-        /* Update (SocketImpl)s' fd */
-        fdAccess.set(s.fd, newfd);
-        /* Update socketImpls remote port, address and localport */
-        InetSocketAddress isa = isaa[0];
-        s.port = isa.getPort();
-        s.address = isa.getAddress();
-        s.localport = localport;
-    }
-
-    @Override
-    int socketAvailable() throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-        return available0(nativefd);
-    }
-
-    @Override
-    void socketClose0(boolean useDeferredClose/*unused*/) throws IOException {
-        if (fd == null)
-            throw new SocketException("Socket closed");
-
-        if (!fd.valid())
-            return;
-
-        final int nativefd = fdAccess.get(fd);
-        fdAccess.set(fd, -1);
-        close0(nativefd);
-    }
-
-    @Override
-    void socketShutdown(int howto) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-        shutdown0(nativefd, howto);
-    }
-
-    // Intentional fallthrough after SO_REUSEADDR
-    @SuppressWarnings("fallthrough")
-    @Override
-    void socketSetOption(int opt, boolean on, Object value)
-        throws SocketException {
-        int nativefd = checkAndReturnNativeFD();
-
-        if (opt == SO_TIMEOUT) {
-            // Don't enable the socket option on ServerSocket as it's
-            // meaningless (we don't receive on a ServerSocket).
-            if (serverSocket == null) {
-                setSoTimeout0(nativefd, ((Integer)value).intValue());
-            }
-            return;
-        }
-        // SO_REUSEPORT is not supported on Windows.
-        if (opt == SO_REUSEPORT) {
-            throw new UnsupportedOperationException("unsupported option");
-        }
-
-        int optionValue = 0;
-
-        switch(opt) {
-            case SO_REUSEADDR :
-                if (exclusiveBind) {
-                    // SO_REUSEADDR emulated when using exclusive bind
-                    isReuseAddress = on;
-                    return;
-                }
-                // intentional fallthrough
-            case TCP_NODELAY :
-            case SO_OOBINLINE :
-            case SO_KEEPALIVE :
-                optionValue = on ? 1 : 0;
-                break;
-            case SO_SNDBUF :
-            case SO_RCVBUF :
-            case IP_TOS :
-                optionValue = ((Integer)value).intValue();
-                break;
-            case SO_LINGER :
-                if (on) {
-                    optionValue =  ((Integer)value).intValue();
-                } else {
-                    optionValue = -1;
-                }
-                break;
-            default :/* shouldn't get here */
-                throw new SocketException("Option not supported");
-        }
-
-        setIntOption(nativefd, opt, optionValue);
-    }
-
-    @Override
-    int socketGetOption(int opt, Object iaContainerObj) throws SocketException {
-        int nativefd = checkAndReturnNativeFD();
-
-        // SO_BINDADDR is not a socket option.
-        if (opt == SO_BINDADDR) {
-            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)
-            return isReuseAddress? 1 : -1;
-
-        int value = getIntOption(nativefd, opt);
-
-        switch (opt) {
-            case TCP_NODELAY :
-            case SO_OOBINLINE :
-            case SO_KEEPALIVE :
-            case SO_REUSEADDR :
-                return (value == 0) ? -1 : 1;
-        }
-        return value;
-    }
-
-    @Override
-    void socketSendUrgentData(int data) throws IOException {
-        int nativefd = checkAndReturnNativeFD();
-        sendOOB(nativefd, data);
-    }
-
-    private int checkAndReturnNativeFD() throws SocketException {
-        if (fd == null || !fd.valid())
-            throw new SocketException("Socket closed");
-
-        return fdAccess.get(fd);
-    }
-
-    static final int WOULDBLOCK = -2;       // Nothing available (non-blocking)
-
-    static {
-        initIDs();
-    }
-
-    /* Native methods */
-
-    static native void initIDs();
-
-    static native int socket0(boolean stream, boolean v6Only) throws IOException;
-
-    static native void bind0(int fd, InetAddress localAddress, int localport,
-                             boolean exclBind)
-        throws IOException;
-
-    static native int connect0(int fd, InetAddress remote, int remotePort)
-        throws IOException;
-
-    static native void waitForConnect(int fd, int timeout) throws IOException;
-
-    static native int localPort0(int fd) throws IOException;
-
-    static native void localAddress(int fd, InetAddressContainer in) throws SocketException;
-
-    static native void listen0(int fd, int backlog) throws IOException;
-
-    static native int accept0(int fd, InetSocketAddress[] isaa) throws IOException;
-
-    static native void waitForNewConnection(int fd, int timeout) throws IOException;
-
-    static native int available0(int fd) throws IOException;
-
-    static native void close0(int fd) throws IOException;
-
-    static native void shutdown0(int fd, int howto) throws IOException;
-
-    static native void setIntOption(int fd, int cmd, int optionValue) throws SocketException;
-
-    static native void setSoTimeout0(int fd, int timeout) throws SocketException;
-
-    static native int getIntOption(int fd, int cmd) throws SocketException;
-
-    static native void sendOOB(int fd, int data) throws IOException;
-
-    static native void configureBlocking(int fd, boolean blocking) throws IOException;
-}
--- a/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.base/windows/native/libnet/DualStackPlainSocketImpl.c	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2018, 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
@@ -27,8 +27,8 @@
 #include "java_net_DualStackPlainSocketImpl.h"
 #include "java_net_SocketOptions.h"
 
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
+#define SET_BLOCKING     0
+#define SET_NONBLOCKING  1
 
 static jclass isa_class;        /* java.net.InetSocketAddress */
 static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
@@ -60,22 +60,28 @@
  * Signature: (ZZ)I
  */
 JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_socket0
-  (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
+  (JNIEnv *env, jclass clazz, jboolean stream) {
     int fd, rv, opt=0;
+    int type = (stream ? SOCK_STREAM : SOCK_DGRAM);
+    int domain = ipv6_available() ? AF_INET6 : AF_INET;
 
-    fd = NET_Socket(AF_INET6, (stream ? SOCK_STREAM : SOCK_DGRAM), 0);
+    fd = NET_Socket(domain, type, 0);
+
     if (fd == INVALID_SOCKET) {
         NET_ThrowNew(env, WSAGetLastError(), "create");
         return -1;
     }
 
-    rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt, sizeof(opt));
-    if (rv == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "create");
+    if (domain == AF_INET6) {
+        rv = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &opt,
+                        sizeof(opt));
+        if (rv == SOCKET_ERROR) {
+            NET_ThrowNew(env, WSAGetLastError(), "create");
+            closesocket(fd);
+            return -1;
+        }
     }
 
-    SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
-
     return fd;
 }
 
@@ -90,10 +96,11 @@
 {
     SOCKETADDRESS sa;
     int rv, sa_len = 0;
+    jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
 
     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
-                                  &sa_len, JNI_TRUE) != 0) {
-      return;
+                                  &sa_len, v4MappedAddress) != 0) {
+        return;
     }
 
     rv = NET_WinBind(fd, &sa, sa_len, exclBind);
@@ -111,10 +118,11 @@
   (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
     SOCKETADDRESS sa;
     int rv, sa_len = 0;
+    jboolean v4MappedAddress = ipv6_available() ? JNI_TRUE : JNI_FALSE;
 
     if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
-                                  &sa_len, JNI_TRUE) != 0) {
-      return -1;
+                                  &sa_len, v4MappedAddress) != 0) {
+        return -1;
     }
 
     rv = connect(fd, &sa.sa, sa_len);
@@ -124,7 +132,8 @@
             return java_net_DualStackPlainSocketImpl_WOULDBLOCK;
         } else if (err == WSAEADDRNOTAVAIL) {
             JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
-                "connect: Address is invalid on local machine, or port is not valid on remote machine");
+                "connect: Address is invalid on local machine,"
+                " or port is not valid on remote machine");
         } else {
             NET_ThrowNew(env, err, "connect");
         }
@@ -200,6 +209,10 @@
     if (rv == 0) {
         JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
                         "Unable to establish connection");
+    } else if (!ipv6_available() && rv == WSAEADDRNOTAVAIL) {
+        JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
+                        "connect: Address is invalid on local machine,"
+                        " or port is not valid on remote machine");
     } else {
         NET_ThrowNew(env, rv, "connect");
     }
@@ -284,13 +297,7 @@
     newfd = accept(fd, &sa.sa, &len);
 
     if (newfd == INVALID_SOCKET) {
-        if (WSAGetLastError() == -2) {
-            JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
-                            "operation interrupted");
-        } else {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                            "socket closed");
-        }
+        NET_ThrowNew(env, WSAGetLastError(), "accept failed");
         return -1;
     }
 
@@ -298,6 +305,10 @@
 
     ia = NET_SockaddrToInetAddress(env, &sa, &port);
     isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
+    if (isa == NULL) {
+        closesocket(newfd);
+        return -1;
+    }
     (*env)->SetObjectArrayElement(env, isaa, 0, isa);
 
     return newfd;
@@ -402,6 +413,51 @@
 
 /*
  * Class:     java_net_DualStackPlainSocketImpl
+ * Method:    setSoTimeout0
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL
+Java_java_net_DualStackPlainSocketImpl_setSoTimeout0
+  (JNIEnv *env, jclass clazz, jint fd, jint timeout)
+{
+    /*
+     * SO_TIMEOUT is the socket option used to specify the timeout
+     * for ServerSocket.accept and Socket.getInputStream().read.
+     * It does not typically map to a native level socket option.
+     * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
+     * socket option to specify a receive timeout on the socket. This
+     * receive timeout is applicable to Socket only and the socket
+     * option should not be set on ServerSocket.
+     */
+
+    /*
+     * SO_RCVTIMEO is only supported on Microsoft's implementation
+     * of Windows Sockets so if WSAENOPROTOOPT returned then
+     * reset flag and timeout will be implemented using
+     * select() -- see SocketInputStream.socketRead.
+     */
+    if (isRcvTimeoutSupported) {
+        /*
+         * Disable SO_RCVTIMEO if timeout is <= 5 second.
+         */
+        if (timeout <= 5000) {
+            timeout = 0;
+        }
+
+        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
+            sizeof(timeout)) < 0) {
+            int err = WSAGetLastError();
+            if (err == WSAENOPROTOOPT) {
+                isRcvTimeoutSupported = JNI_FALSE;
+            } else {
+                NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
+            }
+        }
+    }
+}
+
+/*
+ * Class:     java_net_DualStackPlainSocketImpl
  * Method:    getIntOption
  * Signature: (II)I
  */
@@ -466,7 +522,7 @@
     int result;
 
     if (blocking == JNI_TRUE) {
-        arg = SET_BLOCKING;    // 0
+        arg = SET_BLOCKING;      // 0
     } else {
         arg = SET_NONBLOCKING;   // 1
     }
--- a/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c	Thu Apr 19 15:37:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,550 +0,0 @@
-/*
- * Copyright (c) 1997, 2018, 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 "net_util.h"
-
-#include "java_net_TwoStacksPlainSocketImpl.h"
-#include "java_net_SocketOptions.h"
-#include "java_net_InetAddress.h"
-
-#define SET_BLOCKING 0
-#define SET_NONBLOCKING 1
-
-static jclass isa_class;        /* java.net.InetSocketAddress */
-static jmethodID isa_ctorID;    /* InetSocketAddress(InetAddress, int) */
-
-/************************************************************************
- * TwoStacksPlainSocketImpl
- */
-
-/*
- * The initIDs function is called whenever TwoStacksPlainSocketImpl is
- * loaded, to cache fieldIds for efficiency. This is called everytime
- * the Java class is loaded.
- *
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    initIDs
- * Signature: ()V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_initIDs
-  (JNIEnv *env, jclass clazz) {
-
-    jclass cls = (*env)->FindClass(env, "java/net/InetSocketAddress");
-    CHECK_NULL(cls);
-    isa_class = (*env)->NewGlobalRef(env, cls);
-    CHECK_NULL(isa_class);
-    isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
-                                     "(Ljava/net/InetAddress;I)V");
-    CHECK_NULL(isa_ctorID);
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    socket0
- * Signature: (ZZ)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_socket0
-  (JNIEnv *env, jclass clazz, jboolean stream, jboolean v6Only /*unused*/) {
-    int fd;
-
-    fd = socket(AF_INET, (stream ? SOCK_STREAM: SOCK_DGRAM), 0);
-    if (fd == INVALID_SOCKET) {
-        NET_ThrowNew(env, WSAGetLastError(), "create");
-        return -1;
-    }
-
-    SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, FALSE);
-
-    return fd;
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    bind0
- * Signature: (ILjava/net/InetAddress;I)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_bind0
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port,
-   jboolean exclBind)
-{
-    SOCKETADDRESS sa;
-    int rv, sa_len = 0;
-    /* family is an int field of iaObj */
-    int family;
-
-    family = getInetAddress_family(env, iaObj);
-    if (family != java_net_InetAddress_IPv4) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "Protocol family not supported");
-        return;
-    }
-
-    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
-                                  &sa_len, JNI_FALSE) != 0) {
-        return;
-    }
-
-    rv = NET_WinBind(fd, &sa, sa_len, exclBind);
-
-    if (rv == SOCKET_ERROR)
-        NET_ThrowNew(env, WSAGetLastError(), "NET_Bind");
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    connect0
- * Signature: (ILjava/net/InetAddress;I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_connect0
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaObj, jint port) {
-    SOCKETADDRESS sa;
-    int rv, sa_len = 0;
-    int family;
-
-    if (NET_InetAddressToSockaddr(env, iaObj, port, &sa,
-                                  &sa_len, JNI_FALSE) != 0) {
-        return -1;
-    }
-
-    family = sa.sa.sa_family;
-    if (family != AF_INET) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "Protocol family not supported");
-        return -1;
-    }
-
-    rv = connect(fd, &sa.sa, sa_len);
-    if (rv == SOCKET_ERROR) {
-        int err = WSAGetLastError();
-        if (err == WSAEWOULDBLOCK) {
-            return java_net_TwoStacksPlainSocketImpl_WOULDBLOCK;
-        } else if (err == WSAEADDRNOTAVAIL) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
-                "connect: Address is invalid on local machine, or port is not valid on remote machine");
-        } else {
-            NET_ThrowNew(env, err, "connect");
-        }
-        return -1;  // return value not important.
-    }
-    return rv;
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    waitForConnect
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_waitForConnect
-  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
-    int rv, retry;
-    int optlen = sizeof(rv);
-    fd_set wr, ex;
-    struct timeval t;
-
-    FD_ZERO(&wr);
-    FD_ZERO(&ex);
-    FD_SET(fd, &wr);
-    FD_SET(fd, &ex);
-    t.tv_sec = timeout / 1000;
-    t.tv_usec = (timeout % 1000) * 1000;
-
-    /*
-     * Wait for timeout, connection established or
-     * connection failed.
-     */
-    rv = select(fd+1, 0, &wr, &ex, &t);
-
-    /*
-     * Timeout before connection is established/failed so
-     * we throw exception and shutdown input/output to prevent
-     * socket from being used.
-     * The socket should be closed immediately by the caller.
-     */
-    if (rv == 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
-                        "connect timed out");
-        shutdown( fd, SD_BOTH );
-        return;
-    }
-    /*
-     * Socket is writable or error occurred. On some Windows editions
-     * the socket will appear writable when the connect fails so we
-     * check for error rather than writable.
-     */
-    if (!FD_ISSET(fd, &ex)) {
-        return;         /* connection established */
-    }
-
-    /*
-     * Connection failed. The logic here is designed to work around
-     * bug on Windows NT whereby using getsockopt to obtain the
-     * last error (SO_ERROR) indicates there is no error. The workaround
-     * on NT is to allow winsock to be scheduled and this is done by
-     * yielding and retrying. As yielding is problematic in heavy
-     * load conditions we attempt up to 3 times to get the error reason.
-     */
-    for (retry=0; retry<3; retry++) {
-        NET_GetSockOpt(fd, SOL_SOCKET, SO_ERROR,
-                       (char*)&rv, &optlen);
-        if (rv) {
-            break;
-        }
-        Sleep(0);
-    }
-
-    if (rv == 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "Unable to establish connection");
-    } else if (rv == WSAEADDRNOTAVAIL) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "ConnectException",
-                        "connect: Address is invalid on local machine,"
-                        " or port is not valid on remote machine");
-    } else {
-        NET_ThrowNew(env, rv, "connect");
-    }
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    localPort0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_localPort0
-  (JNIEnv *env, jclass clazz, jint fd) {
-    SOCKETADDRESS sa;
-    int len = sizeof(sa);
-
-    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
-        if (WSAGetLastError() == WSAENOTSOCK) {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                    "Socket closed");
-        } else {
-            NET_ThrowNew(env, WSAGetLastError(), "getsockname failed");
-        }
-        return -1;
-    }
-    return (int) ntohs((u_short)GET_PORT(&sa));
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    localAddress
- * Signature: (ILjava/net/InetAddressContainer;)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_localAddress
-  (JNIEnv *env, jclass clazz, jint fd, jobject iaContainerObj) {
-    int port;
-    SOCKETADDRESS sa;
-    int len = sizeof(sa);
-    jobject iaObj;
-    jclass iaContainerClass;
-    jfieldID iaFieldID;
-
-    if (getsockname(fd, &sa.sa, &len) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "Error getting socket name");
-        return;
-    }
-    iaObj = NET_SockaddrToInetAddress(env, &sa, &port);
-    CHECK_NULL(iaObj);
-
-    iaContainerClass = (*env)->GetObjectClass(env, iaContainerObj);
-    iaFieldID = (*env)->GetFieldID(env, iaContainerClass, "addr", "Ljava/net/InetAddress;");
-    CHECK_NULL(iaFieldID);
-    (*env)->SetObjectField(env, iaContainerObj, iaFieldID, iaObj);
-}
-
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    listen0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_listen0
-  (JNIEnv *env, jclass clazz, jint fd, jint backlog) {
-    if (listen(fd, backlog) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "listen failed");
-    }
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    accept0
- * Signature: (I[Ljava/net/InetSocketAddress;)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_accept0
-  (JNIEnv *env, jclass clazz, jint fd, jobjectArray isaa) {
-    int newfd, port=0;
-    jobject isa;
-    jobject ia;
-    SOCKETADDRESS sa;
-    int len = sizeof(sa);
-
-    memset((char *)&sa, 0, len);
-    newfd = accept(fd, &sa.sa, &len);
-
-    if (newfd < 0) {
-        if (newfd == -2) {
-            JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
-                            "operation interrupted");
-        } else {
-            JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                            "socket closed");
-        }
-        return -1;
-    }
-
-    SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
-
-    if (sa.sa.sa_family != AF_INET) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException",
-                        "Protocol family not supported");
-        NET_SocketClose(newfd);
-        return -1;
-    }
-
-    ia = NET_SockaddrToInetAddress(env, &sa, &port);
-    isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
-    (*env)->SetObjectArrayElement(env, isaa, 0, isa);
-
-    return newfd;
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    waitForNewConnection
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_waitForNewConnection
-  (JNIEnv *env, jclass clazz, jint fd, jint timeout) {
-    int rv;
-
-    rv = NET_Timeout(fd, timeout);
-    if (rv == 0) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
-                        "Accept timed out");
-    } else if (rv == -1) {
-        JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", "socket closed");
-    } else if (rv == -2) {
-        JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException",
-                        "operation interrupted");
-    }
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    available0
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_available0
-  (JNIEnv *env, jclass clazz, jint fd) {
-    jint available = -1;
-
-    if ((ioctlsocket(fd, FIONREAD, &available)) == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "socket available");
-    }
-
-    return available;
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    close0
- * Signature: (I)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_close0
-  (JNIEnv *env, jclass clazz, jint fd) {
-     NET_SocketClose(fd);
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    shutdown0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_shutdown0
-  (JNIEnv *env, jclass clazz, jint fd, jint howto) {
-    shutdown(fd, howto);
-}
-
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    setIntOption
- * Signature: (III)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_setIntOption
-  (JNIEnv *env, jclass clazz, jint fd, jint cmd, jint value)
-{
-    int level = 0, opt = 0;
-    struct linger linger = {0, 0};
-    char *parg;
-    int arglen;
-
-    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
-        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
-        return;
-    }
-
-    if (opt == java_net_SocketOptions_SO_LINGER) {
-        parg = (char *)&linger;
-        arglen = sizeof(linger);
-        if (value >= 0) {
-            linger.l_onoff = 1;
-            linger.l_linger = (unsigned short)value;
-        } else {
-            linger.l_onoff = 0;
-            linger.l_linger = 0;
-        }
-    } else {
-        parg = (char *)&value;
-        arglen = sizeof(value);
-    }
-
-    if (NET_SetSockOpt(fd, level, opt, parg, arglen) < 0) {
-        NET_ThrowNew(env, WSAGetLastError(), "setsockopt");
-    }
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    setSoTimeout0
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL
-Java_java_net_TwoStacksPlainSocketImpl_setSoTimeout0
-  (JNIEnv *env, jclass clazz, jint fd, jint timeout)
-{
-    /*
-     * SO_TIMEOUT is the socket option used to specify the timeout
-     * for ServerSocket.accept and Socket.getInputStream().read.
-     * It does not typically map to a native level socket option.
-     * For Windows we special-case this and use the SOL_SOCKET/SO_RCVTIMEO
-     * socket option to specify a receive timeout on the socket. This
-     * receive timeout is applicable to Socket only and the socket
-     * option should not be set on ServerSocket.
-     */
-
-    /*
-     * SO_RCVTIMEO is only supported on Microsoft's implementation
-     * of Windows Sockets so if WSAENOPROTOOPT returned then
-     * reset flag and timeout will be implemented using
-     * select() -- see SocketInputStream.socketRead.
-     */
-    if (isRcvTimeoutSupported) {
-        /*
-         * Disable SO_RCVTIMEO if timeout is <= 5 second.
-         */
-        if (timeout <= 5000) {
-            timeout = 0;
-        }
-
-        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout,
-            sizeof(timeout)) < 0) {
-            int err = WSAGetLastError();
-            if (err == WSAENOPROTOOPT) {
-                isRcvTimeoutSupported = JNI_FALSE;
-            } else {
-                NET_ThrowNew(env, err, "setsockopt SO_RCVTIMEO");
-            }
-        }
-    }
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    getIntOption
- * Signature: (II)I
- */
-JNIEXPORT jint JNICALL Java_java_net_TwoStacksPlainSocketImpl_getIntOption
-  (JNIEnv *env, jclass clazz, jint fd, jint cmd)
-{
-    int level = 0, opt = 0;
-    int result=0;
-    struct linger linger = {0, 0};
-    char *arg;
-    int arglen;
-
-    if (NET_MapSocketOption(cmd, &level, &opt) < 0) {
-        JNU_ThrowByName(env, "java/net/SocketException", "Invalid option");
-        return -1;
-    }
-
-    if (opt == java_net_SocketOptions_SO_LINGER) {
-        arg = (char *)&linger;
-        arglen = sizeof(linger);
-    } else {
-        arg = (char *)&result;
-        arglen = sizeof(result);
-    }
-
-    if (NET_GetSockOpt(fd, level, opt, arg, &arglen) < 0) {
-        NET_ThrowNew(env, WSAGetLastError(), "getsockopt");
-        return -1;
-    }
-
-    if (opt == java_net_SocketOptions_SO_LINGER)
-        return linger.l_onoff ? linger.l_linger : -1;
-    else
-        return result;
-}
-
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    sendOOB
- * Signature: (II)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_sendOOB
-  (JNIEnv *env, jclass clazz, jint fd, jint data) {
-    jint n;
-    unsigned char d = (unsigned char) data & 0xff;
-
-    n = send(fd, (char *)&data, 1, MSG_OOB);
-    if (n == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "send");
-    }
-}
-
-/*
- * Class:     java_net_TwoStacksPlainSocketImpl
- * Method:    configureBlocking
- * Signature: (IZ)V
- */
-JNIEXPORT void JNICALL Java_java_net_TwoStacksPlainSocketImpl_configureBlocking
-  (JNIEnv *env, jclass clazz, jint fd, jboolean blocking) {
-    u_long arg;
-    int result;
-
-    if (blocking == JNI_TRUE) {
-        arg = SET_BLOCKING;    // 0
-    } else {
-        arg = SET_NONBLOCKING;   // 1
-    }
-
-    result = ioctlsocket(fd, FIONBIO, &arg);
-    if (result == SOCKET_ERROR) {
-        NET_ThrowNew(env, WSAGetLastError(), "configureBlocking");
-    }
-}
--- a/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/share/native/common/awt/medialib/mlib_ImageCreate.c	Mon Apr 23 12:32:25 2018 +0200
@@ -227,7 +227,7 @@
 }
 
 /***************************************************************/
-mlib_image *mlib_ImageCreateStruct(mlib_type  type,
+JNIEXPORT mlib_image* JNICALL mlib_ImageCreateStruct(mlib_type  type,
                                    mlib_s32   channels,
                                    mlib_s32   width,
                                    mlib_s32   height,
@@ -253,7 +253,7 @@
 }
 
 /***************************************************************/
-mlib_image *mlib_ImageCreate(mlib_type type,
+JNIEXPORT mlib_image* JNICALL mlib_ImageCreate(mlib_type type,
                              mlib_s32  channels,
                              mlib_s32  width,
                              mlib_s32  height)
@@ -352,7 +352,7 @@
 }
 
 /***************************************************************/
-void mlib_ImageDelete(mlib_image *img)
+JNIEXPORT void JNICALL mlib_ImageDelete(mlib_image *img)
 {
   if (img == NULL) return;
   if ((img -> flags & MLIB_IMAGE_USERALLOCATED) == 0) {
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageAffine.c	Mon Apr 23 12:32:25 2018 +0200
@@ -299,7 +299,7 @@
 }
 
 /***************************************************************/
-mlib_status mlib_ImageAffine(mlib_image       *dst,
+JNIEXPORT mlib_status JNICALL mlib_ImageAffine(mlib_image       *dst,
                              const mlib_image *src,
                              const mlib_d64   *mtx,
                              mlib_filter      filter,
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvKernelConvert.c	Mon Apr 23 12:32:25 2018 +0200
@@ -78,7 +78,7 @@
 #endif /* __sparc */
 
 /***************************************************************/
-mlib_status mlib_ImageConvKernelConvert(mlib_s32       *ikernel,
+JNIEXPORT mlib_status JNICALL mlib_ImageConvKernelConvert(mlib_s32       *ikernel,
                                         mlib_s32       *iscale,
                                         const mlib_d64 *fkernel,
                                         mlib_s32       m,
--- a/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/share/native/libmlib_image/mlib_ImageConvMxN.c	Mon Apr 23 12:32:25 2018 +0200
@@ -90,7 +90,7 @@
 #include "mlib_ImageConvEdge.h"
 
 /***************************************************************/
-mlib_status mlib_ImageConvMxN(mlib_image       *dst,
+JNIEXPORT mlib_status JNICALL mlib_ImageConvMxN(mlib_image       *dst,
                               const mlib_image *src,
                               const mlib_s32   *kernel,
                               mlib_s32         m,
--- a/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/share/native/libmlib_image/mlib_c_ImageLookUp.c	Mon Apr 23 12:32:25 2018 +0200
@@ -78,7 +78,7 @@
 #include "mlib_c_ImageLookUp.h"
 
 /***************************************************************/
-mlib_status mlib_ImageLookUp(mlib_image       *dst,
+JNIEXPORT mlib_status JNICALL mlib_ImageLookUp(mlib_image       *dst,
                              const mlib_image *src,
                              const void       **table)
 {
--- a/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/share/native/libsplashscreen/splashscreen_impl.h	Mon Apr 23 12:32:25 2018 +0200
@@ -132,9 +132,6 @@
 
 unsigned SplashTime();
 char* SplashConvertStringAlloc(const char* in, int *size);
-jboolean SplashGetScaledImageName(const char* jarName,
-                 const char* fileName, float *scaleFactor,
-                 char *scaleImageName, const size_t scaledImageNameLength);
 void SplashLock(Splash * splash);
 void SplashUnlock(Splash * splash);
 
@@ -157,8 +154,7 @@
 void SplashUpdateScreenData(Splash * splash);
 
 void SplashCleanup(Splash * splash);
-void SplashSetScaleFactor(float scaleFactor);
-int  SplashGetScaledImgNameMaxPstfixLen(const char *fileName);
+
 void cleanUp(char *fName, char *xName, char *pctName, float *scaleFactor);
 jboolean GetScaledImageName(const char *fileName, char *scaledImgName,
                   float *scaleFactor, const size_t scaledImageLength);
--- a/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/java.desktop/windows/native/libsplashscreen/splashscreen_sys.c	Mon Apr 23 12:32:25 2018 +0200
@@ -574,7 +574,7 @@
     PostMessage(splash->hWnd, WM_SPLASHRECONFIGURE, 0, 0);
 }
 
-jboolean
+JNIEXPORT jboolean JNICALL
 SplashGetScaledImageName(const char* jarName, const char* fileName,
                            float *scaleFactor, char *scaleImageName,
                            const size_t scaledImageLength)
--- a/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/jdk.aot/share/classes/jdk.tools.jaotc.binformat/src/jdk/tools/jaotc/binformat/BinaryContainer.java	Mon Apr 23 12:32:25 2018 +0200
@@ -230,6 +230,8 @@
 
         {"JVMCIRuntime::monitorenter", "_aot_jvmci_runtime_monitorenter"},
         {"JVMCIRuntime::monitorexit", "_aot_jvmci_runtime_monitorexit"},
+        {"JVMCIRuntime::object_notify", "_aot_object_notify"},
+        {"JVMCIRuntime::object_notifyAll", "_aot_object_notifyAll"},
         {"JVMCIRuntime::log_object", "_aot_jvmci_runtime_log_object"},
         {"JVMCIRuntime::log_printf", "_aot_jvmci_runtime_log_printf"},
         {"JVMCIRuntime::vm_message", "_aot_jvmci_runtime_vm_message"},
--- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java	Thu Apr 19 15:37:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 2003, 2004, 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.
- */
-
-package sun.nio.cs.ext;
-
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.util.Arrays;
-import sun.nio.cs.DoubleByte;
-import sun.nio.cs.HistoricallyNamedCharset;
-import static sun.nio.cs.CharsetMapping.*;
-
-public class IBM942C extends Charset implements HistoricallyNamedCharset
-{
-    public IBM942C() {
-        super("x-IBM942C", ExtendedCharsets.aliasesFor("x-IBM942C"));
-    }
-
-    public String historicalName() {
-        return "Cp942C";
-    }
-
-    public boolean contains(Charset cs) {
-        return ((cs.name().equals("US-ASCII"))
-                || (cs instanceof IBM942C));
-    }
-
-    public CharsetDecoder newDecoder() {
-        return new DoubleByte.Decoder(this,
-                                      IBM942.b2c,
-                                      b2cSB,
-                                      0x40,
-                                      0xfc);
-    }
-
-    public CharsetEncoder newEncoder() {
-        return new DoubleByte.Encoder(this, c2b, c2bIndex);
-    }
-
-    final static char[] b2cSB;
-    final static char[] c2b;
-    final static char[] c2bIndex;
-
-    static {
-        IBM942.initb2c();
-
-        // the mappings need udpate are
-        //    u+001a  <-> 0x1a
-        //    u+001c  <-> 0x1c
-        //    u+005c  <-> 0x5c
-        //    u+007e  <-> 0x7e
-        //    u+007f  <-> 0x7f
-
-        b2cSB = Arrays.copyOf(IBM942.b2cSB, IBM942.b2cSB.length);
-        b2cSB[0x1a] = 0x1a;
-        b2cSB[0x1c] = 0x1c;
-        b2cSB[0x5c] = 0x5c;
-        b2cSB[0x7e] = 0x7e;
-        b2cSB[0x7f] = 0x7f;
-
-        IBM942.initc2b();
-        c2b = Arrays.copyOf(IBM942.c2b, IBM942.c2b.length);
-        c2bIndex = Arrays.copyOf(IBM942.c2bIndex, IBM942.c2bIndex.length);
-        c2b[c2bIndex[0] + 0x1a] = 0x1a;
-        c2b[c2bIndex[0] + 0x1c] = 0x1c;
-        c2b[c2bIndex[0] + 0x5c] = 0x5c;
-        c2b[c2bIndex[0] + 0x7e] = 0x7e;
-        c2b[c2bIndex[0] + 0x7f] = 0x7f;
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM942C.java.template	Mon Apr 23 12:32:25 2018 +0200
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2003, 2018, 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.
+ */
+
+package $PACKAGE$;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
+import sun.nio.cs.DoubleByte;
+import sun.nio.cs.HistoricallyNamedCharset;
+import static sun.nio.cs.CharsetMapping.*;
+
+public class IBM942C extends Charset implements HistoricallyNamedCharset
+{
+    public IBM942C() {
+        super("x-IBM942C", $ALIASES$);
+    }
+
+    public String historicalName() {
+        return "Cp942C";
+    }
+
+    public boolean contains(Charset cs) {
+        return ((cs.name().equals("US-ASCII"))
+                || (cs instanceof IBM942C));
+    }
+
+    public CharsetDecoder newDecoder() {
+        return new DoubleByte.Decoder(this,
+                                      IBM942.b2c,
+                                      b2cSB,
+                                      0x40,
+                                      0xfc);
+    }
+
+    public CharsetEncoder newEncoder() {
+        return new DoubleByte.Encoder(this, c2b, c2bIndex);
+    }
+
+    final static char[] b2cSB;
+    final static char[] c2b;
+    final static char[] c2bIndex;
+
+    static {
+        IBM942.initb2c();
+
+        // the mappings need udpate are
+        //    u+001a  <-> 0x1a
+        //    u+001c  <-> 0x1c
+        //    u+005c  <-> 0x5c
+        //    u+007e  <-> 0x7e
+        //    u+007f  <-> 0x7f
+
+        b2cSB = Arrays.copyOf(IBM942.b2cSB, IBM942.b2cSB.length);
+        b2cSB[0x1a] = 0x1a;
+        b2cSB[0x1c] = 0x1c;
+        b2cSB[0x5c] = 0x5c;
+        b2cSB[0x7e] = 0x7e;
+        b2cSB[0x7f] = 0x7f;
+
+        IBM942.initc2b();
+        c2b = Arrays.copyOf(IBM942.c2b, IBM942.c2b.length);
+        c2bIndex = Arrays.copyOf(IBM942.c2bIndex, IBM942.c2bIndex.length);
+        c2b[c2bIndex[0] + 0x1a] = 0x1a;
+        c2b[c2bIndex[0] + 0x1c] = 0x1c;
+        c2b[c2bIndex[0] + 0x5c] = 0x5c;
+        c2b[c2bIndex[0] + 0x7e] = 0x7e;
+        c2b[c2bIndex[0] + 0x7f] = 0x7f;
+    }
+}
--- a/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java	Thu Apr 19 15:37:43 2018 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,85 +0,0 @@
-/*
- * Copyright (c) 2003, 2004, 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.
- */
-
-package sun.nio.cs.ext;
-
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CharsetEncoder;
-import java.util.Arrays;
-import sun.nio.cs.DoubleByte;
-import sun.nio.cs.HistoricallyNamedCharset;
-
-public class IBM943C extends Charset implements HistoricallyNamedCharset
-{
-
-    public IBM943C() {
-        super("x-IBM943C", ExtendedCharsets.aliasesFor("x-IBM943C"));
-    }
-
-    public String historicalName() {
-        return "Cp943C";
-    }
-
-    public boolean contains(Charset cs) {
-        return ((cs.name().equals("US-ASCII"))
-                || (cs instanceof IBM943C));
-    }
-
-    public CharsetDecoder newDecoder() {
-        return new DoubleByte.Decoder(this,
-                                      IBM943.b2c,
-                                      b2cSB,
-                                      0x40,
-                                      0xfc);
-    }
-
-    public CharsetEncoder newEncoder() {
-        return new DoubleByte.Encoder(this, c2b, c2bIndex);
-    }
-
-    final static char[] b2cSB;
-    final static char[] c2b;
-    final static char[] c2bIndex;
-
-    static {
-        IBM943.initb2c();
-        b2cSB = new char[0x100];
-        for (int i = 0; i < 0x80; i++) {
-            b2cSB[i] = (char)i;
-        }
-        for (int i = 0x80; i < 0x100; i++) {
-            b2cSB[i] = IBM943.b2cSB[i];
-        }
-
-        IBM943.initc2b();
-        c2b = Arrays.copyOf(IBM943.c2b, IBM943.c2b.length);
-        c2bIndex = Arrays.copyOf(IBM943.c2bIndex, IBM943.c2bIndex.length);
-        for (char c = '\0'; c < '\u0080'; ++c) {
-            int index = c2bIndex[c >> 8];
-            c2b[index + (c & 0xff)] = c;
-        }
-    }
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.charsets/share/classes/sun/nio/cs/ext/IBM943C.java.template	Mon Apr 23 12:32:25 2018 +0200
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003, 2018, 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.
+ */
+
+package $PACKAGE$;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CharsetEncoder;
+import java.util.Arrays;
+import sun.nio.cs.DoubleByte;
+import sun.nio.cs.HistoricallyNamedCharset;
+
+public class IBM943C extends Charset implements HistoricallyNamedCharset
+{
+
+    public IBM943C() {
+        super("x-IBM943C", $ALIASES$);
+    }
+
+    public String historicalName() {
+        return "Cp943C";
+    }
+
+    public boolean contains(Charset cs) {
+        return ((cs.name().equals("US-ASCII"))
+                || (cs instanceof IBM943C));
+    }
+
+    public CharsetDecoder newDecoder() {
+        return new DoubleByte.Decoder(this,
+                                      IBM943.b2c,
+                                      b2cSB,
+                                      0x40,
+                                      0xfc);
+    }
+
+    public CharsetEncoder newEncoder() {
+        return new DoubleByte.Encoder(this, c2b, c2bIndex);
+    }
+
+    final static char[] b2cSB;
+    final static char[] c2b;
+    final static char[] c2bIndex;
+
+    static {
+        IBM943.initb2c();
+        b2cSB = new char[0x100];
+        for (int i = 0; i < 0x80; i++) {
+            b2cSB[i] = (char)i;
+        }
+        for (int i = 0x80; i < 0x100; i++) {
+            b2cSB[i] = IBM943.b2cSB[i];
+        }
+
+        IBM943.initc2b();
+        c2b = Arrays.copyOf(IBM943.c2b, IBM943.c2b.length);
+        c2bIndex = Arrays.copyOf(IBM943.c2bIndex, IBM943.c2bIndex.length);
+        for (char c = '\0'; c < '\u0080'; ++c) {
+            int index = c2bIndex[c >> 8];
+            c2b[index + (c & 0xff)] = c;
+        }
+    }
+}
--- a/src/jdk.pack/share/native/unpack200/main.cpp	Thu Apr 19 15:37:43 2018 +0200
+++ b/src/jdk.pack/share/native/unpack200/main.cpp	Mon Apr 23 12:32:25 2018 +0200
@@ -59,7 +59,7 @@
 #include "unpack.h"
 
 
-JNIEXPORT int JNICALL
+JNIEXPORT int
 main(int argc, char **argv) {
     return unpacker::run(argc, argv);
 }
--- a/test/hotspot/jtreg/TEST.groups	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/hotspot/jtreg/TEST.groups	Mon Apr 23 12:32:25 2018 +0200
@@ -73,7 +73,13 @@
 
 hotspot_not_fast_compiler = \
   :hotspot_compiler \
-  -:tier1_compiler
+  -:tier1_compiler \
+  -:hotspot_slow_compiler
+
+hotspot_slow_compiler = \
+  compiler/codegen/aes \
+  compiler/codecache/stress \
+  compiler/gcbarriers/PreserveFPRegistersTest.java
 
 tier1_compiler_1 = \
   compiler/arraycopy/ \
@@ -105,9 +111,7 @@
   compiler/integerArithmetic/ \
   compiler/interpreter/ \
   compiler/jvmci/ \
-  -compiler/codegen/aes \
-  -compiler/codecache/stress \
-  -compiler/gcbarriers/PreserveFPRegistersTest.java
+  -:hotspot_slow_compiler
 
 tier1_compiler_3 = \
   compiler/intrinsics/ \
@@ -136,12 +140,21 @@
 
 ctw_1 = \
   applications/ctw/modules/ \
-  -:ctw_2
+  -:ctw_2 \
+  -:ctw_3
 
 ctw_2 = \
   applications/ctw/modules/java_base.java \
   applications/ctw/modules/java_desktop.java
 
+ctw_3 = \
+  applications/ctw/modules/javafx_graphics.java \
+  applications/ctw/modules/java_xml.java \
+  applications/ctw/modules/jdk_compiler.java \
+  applications/ctw/modules/jdk_internal_vm_compiler.java \
+  applications/ctw/modules/jdk_localedata.java \
+  applications/ctw/modules/jdk_scripting_nashorn.java \
+
 tier1_gc = \
   :tier1_gc_1 \
   :tier1_gc_2 \
--- a/test/hotspot/jtreg/compiler/aot/fingerprint/CDSDumper.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/CDSDumper.java	Mon Apr 23 12:32:25 2018 +0200
@@ -31,18 +31,19 @@
 import jdk.test.lib.process.ProcessTools;
 
 // Usage:
-// java CDSDumper <classpath> <classlist> <archive> <class1> <class2> ...
+// java CDSDumper <classpath> <classlist> <archive> <heapsize> <class1> <class2> ...
 public class CDSDumper {
     public static void main(String[] args) throws Exception {
         String classpath = args[0];
         String classlist = args[1];
         String archive = args[2];
+        String heapsize = args[3];
 
         // Prepare the classlist
         FileOutputStream fos = new FileOutputStream(classlist);
         PrintStream ps = new PrintStream(fos);
 
-        for (int i=3; i<args.length; i++) {
+        for (int i=4; i<args.length; i++) {
             ps.println(args[i].replace('.', '/'));
         }
         ps.close();
@@ -50,6 +51,7 @@
 
         // Dump the archive
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            heapsize,
             "-XX:+IgnoreUnrecognizedVMOptions",
             "-XX:+UnlockCommercialFeatures",
             "-XX:+UseAppCDS",
@@ -58,9 +60,12 @@
             "-XX:ExtraSharedClassListFile=" + classlist,
             "-XX:SharedArchiveFile=" + archive,
             "-Xshare:dump",
+            "-Xlog:gc+heap+coops",
             "-Xlog:cds");
 
         OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        System.out.println("[stdout = " + output.getStdout() + "]");
+        System.out.println("[stderr = " + output.getStderr() + "]");
         output.shouldContain("Loading classes to share");
         output.shouldHaveExitValue(0);
     }
--- a/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChangedCDS.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/hotspot/jtreg/compiler/aot/fingerprint/SelfChangedCDS.java	Mon Apr 23 12:32:25 2018 +0200
@@ -36,7 +36,7 @@
  *      -class compiler.aot.fingerprint.Blah
  *
  * @run driver ClassFileInstaller -jar SelfChangedCDS.jar compiler.aot.fingerprint.Blah
- * @run main compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa
+ * @run main compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa -showversion
  *      compiler.aot.fingerprint.Blah
  *
  * @run main compiler.aot.fingerprint.CDSRunner -cp SelfChangedCDS.jar
@@ -46,6 +46,7 @@
  *      -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
  *      -XX:+IgnoreUnrecognizedVMOptions
  *      -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
+ *      -Xlog:cds -Xlog:gc+heap+coops
  *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
  *      compiler.aot.fingerprint.Blah TEST-UNMODIFIED
  *
@@ -61,6 +62,26 @@
  *      -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
  *      -XX:+IgnoreUnrecognizedVMOptions
  *      -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
+ *      -Xlog:cds -Xlog:gc+heap+coops
  *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
  *      compiler.aot.fingerprint.Blah TEST-MODIFIED
+ *
+ *
+ * @run driver compiler.aot.AotCompiler -libname libSelfChanged.so
+ *      -class compiler.aot.fingerprint.Blah
+ *      -extraopt -Xmx512m
+ *
+ * @run main compiler.aot.fingerprint.CDSDumper SelfChangedCDS.jar SelfChangedCDS.classlist SelfChangedCDS.jsa -Xmx512m
+ *      compiler.aot.fingerprint.Blah
+ *
+ * @run main compiler.aot.fingerprint.CDSRunner -Xmx512m -cp SelfChangedCDS.jar
+ *      compiler.aot.fingerprint.Blah TEST-UNMODIFIED
+ * @run main compiler.aot.fingerprint.CDSRunner -Xmx512m -cp SelfChangedCDS.jar
+ *      -XX:+UseAOT -XX:+PrintAOT -XX:AOTLibrary=./libSelfChanged.so
+ *      -XX:+UnlockDiagnosticVMOptions -XX:SharedArchiveFile=SelfChangedCDS.jsa
+ *      -XX:+IgnoreUnrecognizedVMOptions
+ *      -Xshare:auto -XX:+UnlockCommercialFeatures -XX:+UseAppCDS -showversion
+ *      -Xlog:cds -Xlog:gc+heap+coops
+ *      -Xlog:aot+class+fingerprint=trace -Xlog:aot+class+load=trace
+ *      compiler.aot.fingerprint.Blah TEST-UNMODIFIED
  */
--- a/test/hotspot/jtreg/runtime/whitebox/WBStackSize.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/hotspot/jtreg/runtime/whitebox/WBStackSize.java	Mon Apr 23 12:32:25 2018 +0200
@@ -82,7 +82,9 @@
     }
 
     public static void main(String[] args) {
-        long configStackSize = wb.getIntxVMFlag("ThreadStackSize") * K;
+        boolean isCompilerThread = Thread.currentThread().getName().indexOf(" CompilerThread") > 0;
+        long configStackSize = isCompilerThread ? wb.getIntxVMFlag("CompilerThreadStackSize") * K
+                                                : wb.getIntxVMFlag("ThreadStackSize") * K;
         System.out.println("ThreadStackSize VM option: " + configStackSize);
 
         long stackProtectionSize = wb.getIntxVMFlag("StackShadowPages") * wb.getVMPageSize();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/Socket/RejectIPv6.java	Mon Apr 23 12:32:25 2018 +0200
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2018, 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 8201510
+ * @summary Make sure IPv6 addresses are rejected when the System option
+ *          java.net.preferIPv4Stack is set to true
+ * @run main/othervm -Djava.net.preferIPv4Stack=true RejectIPv6
+ */
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+public class RejectIPv6 {
+
+    public static void main(String [] argv) throws Throwable {
+        ServerSocket serverSocket = new ServerSocket(0);
+        serverSocket.setSoTimeout(1000);
+        int serverPort = serverSocket.getLocalPort();
+        Socket clientSocket = new Socket();
+
+        test("bind", () -> clientSocket.bind(
+                new InetSocketAddress("::1", 0)));
+
+        test("connect", () -> clientSocket.connect(
+                new InetSocketAddress("::1", serverPort), 1000));
+    }
+
+    static void test(String msg, CodeToTest codeToTest) throws Throwable {
+        Thread client = new Thread(() ->
+            {
+                try {
+                    codeToTest.run();
+                    throw new RuntimeException(msg +
+                            " failed to reject IPv6 address");
+                } catch (SocketException ok) {
+                } catch (Exception exc) {
+                    throw new RuntimeException("unexpected", exc);
+                }
+            });
+        client.start();
+        client.join();
+    }
+
+    interface CodeToTest {
+        void run() throws Exception;
+    }
+}
--- a/test/jdk/java/net/Socket/setReuseAddress/Basic.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/jdk/java/net/Socket/setReuseAddress/Basic.java	Mon Apr 23 12:32:25 2018 +0200
@@ -25,11 +25,15 @@
  * @test
  * @bug 4476378
  * @summary Check the specific behaviour of the setReuseAddress(boolean)
- * method.
+ *          method.
  * @run main Basic
  * @run main/othervm -Dsun.net.useExclusiveBind Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind=true Basic
  * @run main/othervm -Djava.net.preferIPv4Stack=true Basic
- * @run main/othervm -Dsun.net.useExclusiveBind -Djava.net.preferIPv4Stack=true Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind
+ *                   -Djava.net.preferIPv4Stack=true Basic
+ * @run main/othervm -Dsun.net.useExclusiveBind=true
+ *                   -Djava.net.preferIPv4Stack=true Basic
  */
 import java.net.*;
 
--- a/test/jdk/java/net/Socket/setReuseAddress/Restart.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/jdk/java/net/Socket/setReuseAddress/Restart.java	Mon Apr 23 12:32:25 2018 +0200
@@ -28,8 +28,12 @@
  *          after a crash.
  * @run main Restart
  * @run main/othervm -Dsun.net.useExclusiveBind Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind=true Restart
  * @run main/othervm -Djava.net.preferIPv4Stack=true Restart
- * @run main/othervm -Dsun.net.useExclusiveBind -Djava.net.preferIPv4Stack=true Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind
+ *                   -Djava.net.preferIPv4Stack=true Restart
+ * @run main/othervm -Dsun.net.useExclusiveBind=true
+ *                   -Djava.net.preferIPv4Stack=true Restart
  */
 import java.net.*;
 
--- a/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/jdk/java/nio/channels/AsynchronousSocketChannel/Basic.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2018, 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
@@ -25,8 +25,8 @@
  * @bug 4607272 6842687 6878369 6944810 7023403
  * @summary Unit test for AsynchronousSocketChannel(use -Dseed=X to set PRNG seed)
  * @library /test/lib
- * @build jdk.test.lib.RandomFactory
- * @run main Basic -skipSlowConnectTest
+ * @build jdk.test.lib.RandomFactory jdk.test.lib.Utils
+ * @run main/othervm/timeout=600 Basic -skipSlowConnectTest
  * @key randomness intermittent
  */
 
@@ -79,11 +79,16 @@
         private final InetSocketAddress address;
 
         Server() throws IOException {
-            ssc = ServerSocketChannel.open().bind(new InetSocketAddress(0));
+            this(0);
+        }
 
-            InetAddress lh = InetAddress.getLocalHost();
-            int port = ((InetSocketAddress)(ssc.getLocalAddress())).getPort();
-            address = new InetSocketAddress(lh, port);
+        Server(int recvBufSize) throws IOException {
+            ssc = ServerSocketChannel.open();
+            if (recvBufSize > 0) {
+                ssc.setOption(SO_RCVBUF, recvBufSize);
+            }
+            ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+            address = (InetSocketAddress)ssc.getLocalAddress();
         }
 
         InetSocketAddress address() {
@@ -293,7 +298,7 @@
 
         System.out.println("-- asynchronous close when reading --");
 
-        try (Server server = new Server()) {
+        try (Server server = new Server(1)) {
             ch = AsynchronousSocketChannel.open();
             ch.connect(server.address()).get();
 
@@ -325,6 +330,8 @@
 
             ch = AsynchronousSocketChannel.open();
             ch.connect(server.address()).get();
+            SocketChannel peer = server.accept();
+            peer.setOption(SO_RCVBUF, 1);
 
             final AtomicReference<Throwable> writeException =
                 new AtomicReference<Throwable>();
@@ -333,10 +340,13 @@
             final AtomicInteger numCompleted = new AtomicInteger();
             ch.write(genBuffer(), ch, new CompletionHandler<Integer,AsynchronousSocketChannel>() {
                 public void completed(Integer result, AsynchronousSocketChannel ch) {
+                    System.out.println("completed write to async channel: " + result);
                     numCompleted.incrementAndGet();
                     ch.write(genBuffer(), ch, this);
+                    System.out.println("started another write to async channel: " + result);
                 }
                 public void failed(Throwable x, AsynchronousSocketChannel ch) {
+                    System.out.println("failed write to async channel");
                     writeException.set(x);
                 }
             });
@@ -347,7 +357,8 @@
             // the internal channel state indicates it is writing
             int prevNumCompleted = numCompleted.get();
             do {
-                Thread.sleep(1000);
+                Thread.sleep((long)(1000 * jdk.test.lib.Utils.TIMEOUT_FACTOR));
+                System.out.println("check if buffer is filled up");
                 if (numCompleted.get() == prevNumCompleted) {
                     break;
                 }
@@ -357,14 +368,19 @@
             // attempt a concurrent write -
             // should fail with WritePendingException
             try {
+                System.out.println("concurrent write to async channel");
                 ch.write(genBuffer());
+                System.out.format("prevNumCompleted: %d, numCompleted: %d%n",
+                                  prevNumCompleted, numCompleted.get());
                 throw new RuntimeException("WritePendingException expected");
             } catch (WritePendingException x) {
             }
 
             // close channel - should cause initial write to complete
+            System.out.println("closing async channel...");
             ch.close();
-            server.accept().close();
+            System.out.println("closed async channel");
+            peer.close();
 
             // wait for exception
             while (writeException.get() == null) {
--- a/test/jdk/java/util/zip/DeInflate.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/jdk/java/util/zip/DeInflate.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2018, 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
@@ -23,17 +23,23 @@
 
 /**
  * @test
- * @bug 7110149 8184306
+ * @bug 7110149 8184306 6341887
  * @summary Test basic deflater & inflater functionality
  * @key randomness
  */
 
 import java.io.*;
+import java.nio.*;
 import java.util.*;
 import java.util.zip.*;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+
 public class DeInflate {
 
+    private static Random rnd = new Random();
+
+
     static void checkStream(Deflater def, byte[] in, int len,
                             byte[] out1, byte[] out2, boolean nowrap)
         throws Throwable
@@ -61,6 +67,57 @@
         }
     }
 
+    static void checkByteBuffer(Deflater def, Inflater inf,
+                                ByteBuffer in, ByteBuffer out1, ByteBuffer out2,
+                                byte[] expected, int len, byte[] result,
+                                boolean out1ReadOnlyWhenInflate)
+            throws Throwable {
+        def.reset();
+        inf.reset();
+
+        def.setInput(in);
+        def.finish();
+        int m = def.deflate(out1);
+
+        out1.flip();
+        if (out1ReadOnlyWhenInflate)
+            out1 = out1.asReadOnlyBuffer();
+        inf.setInput(out1);
+        int n = inf.inflate(out2);
+
+        out2.flip();
+        out2.get(result, 0, n);
+
+        if (n != len || out2.position() != len ||
+            !Arrays.equals(Arrays.copyOf(expected, len), Arrays.copyOf(result, len)) ||
+            inf.inflate(result) != 0) {
+            throw new RuntimeException("De/inflater(buffer) failed:" + def);
+        }
+    }
+
+    static void checkByteBufferReadonly(Deflater def, Inflater inf,
+                                        ByteBuffer in, ByteBuffer out1, ByteBuffer out2)
+            throws Throwable {
+        def.reset();
+        inf.reset();
+        def.setInput(in);
+        def.finish();
+        int m = -1;
+        if (!out2.isReadOnly())
+            out2 = out2.asReadOnlyBuffer();
+        try {
+            m = def.deflate(out2);
+            throw new RuntimeException("deflater: ReadOnlyBufferException: failed");
+        } catch (ReadOnlyBufferException robe) {}
+        m = def.deflate(out1);
+        out1.flip();
+        inf.setInput(out1);
+        try {
+            inf.inflate(out2);
+            throw new RuntimeException("inflater: ReadOnlyBufferException: failed");
+        } catch (ReadOnlyBufferException robe) {}
+    }
+
     static void check(Deflater def, byte[] in, int len,
                       byte[] out1, byte[] out2, boolean nowrap)
         throws Throwable
@@ -83,6 +140,107 @@
                               m, n, len, Arrays.equals(in, out2));
             throw new RuntimeException("De/inflater failed:" + def);
         }
+
+        // readable
+        Arrays.fill(out1, (byte)0);
+        Arrays.fill(out2, (byte)0);
+        ByteBuffer bbIn = ByteBuffer.wrap(in, 0, len);
+        ByteBuffer bbOut1 = ByteBuffer.wrap(out1);
+        ByteBuffer bbOut2 = ByteBuffer.wrap(out2);
+        checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, false);
+        checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+
+        // readonly in
+        Arrays.fill(out1, (byte)0);
+        Arrays.fill(out2, (byte)0);
+        bbIn = ByteBuffer.wrap(in, 0, len).asReadOnlyBuffer();
+        bbOut1 = ByteBuffer.wrap(out1);
+        bbOut2 = ByteBuffer.wrap(out2);
+        checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, false);
+        checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+
+        // readonly out1 when inflate
+        Arrays.fill(out1, (byte)0);
+        Arrays.fill(out2, (byte)0);
+        bbIn = ByteBuffer.wrap(in, 0, len);
+        bbOut1 = ByteBuffer.wrap(out1);
+        bbOut2 = ByteBuffer.wrap(out2);
+        checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, true);
+        checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+
+        // direct
+        bbIn = ByteBuffer.allocateDirect(in.length);
+        bbIn.put(in, 0, n).flip();
+        bbOut1 = ByteBuffer.allocateDirect(out1.length);
+        bbOut2 = ByteBuffer.allocateDirect(out2.length);
+        checkByteBuffer(def, inf, bbIn, bbOut1, bbOut2, in, len, out2, false);
+        checkByteBufferReadonly(def, inf, bbIn, bbOut1, bbOut2);
+    }
+
+    static void checkDict(Deflater def, Inflater inf, byte[] src,
+                          byte[] dstDef, byte[] dstInf,
+                          ByteBuffer dictDef,  ByteBuffer dictInf) throws Throwable {
+        def.reset();
+        inf.reset();
+
+        def.setDictionary(dictDef);
+        def.setInput(src);
+        def.finish();
+        int n = def.deflate(dstDef);
+
+        inf.setInput(dstDef, 0, n);
+        n = inf.inflate(dstInf);
+        if (n != 0 || !inf.needsDictionary()) {
+            throw new RuntimeException("checkDict failed: need dict to continue");
+        }
+        inf.setDictionary(dictInf);
+        n = inf.inflate(dstInf);
+        // System.out.println("result: " + new String(dstInf, 0, n));
+        if (n != src.length || !Arrays.equals(Arrays.copyOf(dstInf, n), src)) {
+            throw new RuntimeException("checkDict failed: inflate result");
+        }
+    }
+
+    static void checkDict(int level, int strategy) throws Throwable {
+
+        Deflater def = newDeflater(level, strategy, false, new byte[0]);
+        Inflater inf = new Inflater();
+
+        byte[] src = "hello world, hello world, hello sherman".getBytes();
+        byte[] dict = "hello".getBytes();
+
+        byte[] dstDef = new byte[1024];
+        byte[] dstInf = new byte[1024];
+
+        def.setDictionary(dict);
+        def.setInput(src);
+        def.finish();
+        int n = def.deflate(dstDef);
+
+        inf.setInput(dstDef, 0, n);
+        n = inf.inflate(dstInf);
+        if (n != 0 || !inf.needsDictionary()) {
+            throw new RuntimeException("checkDict failed: need dict to continue");
+        }
+        inf.setDictionary(dict);
+        n = inf.inflate(dstInf);
+        //System.out.println("result: " + new String(dstInf, 0, n));
+        if (n != src.length || !Arrays.equals(Arrays.copyOf(dstInf, n), src)) {
+            throw new RuntimeException("checkDict failed: inflate result");
+        }
+
+        ByteBuffer dictDef = ByteBuffer.wrap(dict);
+        ByteBuffer dictInf = ByteBuffer.wrap(dict);
+        checkDict(def, inf, src, dstDef, dstInf, dictDef, dictInf);
+
+        dictDef = ByteBuffer.allocateDirect(dict.length);
+        dictInf = ByteBuffer.allocateDirect(dict.length);
+        dictDef.put(dict).flip();
+        dictInf.put(dict).flip();
+        checkDict(def, inf, src, dstDef, dstInf, dictDef, dictInf);
+
+        def.end();
+        inf.end();
     }
 
     private static Deflater newDeflater(int level, int strategy, boolean dowrap, byte[] tmp) {
@@ -109,7 +267,7 @@
     public static void main(String[] args) throws Throwable {
 
         byte[] dataIn = new byte[1024 * 512];
-        new Random().nextBytes(dataIn);
+        rnd.nextBytes(dataIn);
         byte[] dataOut1 = new byte[dataIn.length + 1024];
         byte[] dataOut2 = new byte[dataIn.length];
 
@@ -130,6 +288,7 @@
                         // use a new deflater
                         Deflater def = newDeflater(level, strategy, dowrap, dataOut2);
                         check(def, dataIn, len, dataOut1, dataOut2, dowrap);
+                        def.end();
 
                         // reuse the deflater (with reset) and test on stream, which
                         // uses a "smaller" buffer (smaller than the overall data)
@@ -137,6 +296,8 @@
                         checkStream(def, dataIn, len, dataOut1, dataOut2, dowrap);
                     }
                 }
+                // test setDictionary()
+                checkDict(level, strategy);
             }
         }
     }
--- a/test/jdk/java/util/zip/FlaterTest.java	Thu Apr 19 15:37:43 2018 +0200
+++ b/test/jdk/java/util/zip/FlaterTest.java	Mon Apr 23 12:32:25 2018 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2018, 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
@@ -23,13 +23,12 @@
 
 /**
  * @test
- * @bug 6348045
+ * @bug 6348045 6341887
  * @summary GZipOutputStream/InputStream goes critical(calls JNI_Get*Critical)
  * and causes slowness.  This test uses Deflater and Inflater directly.
  * @key randomness
  */
 
-import java.io.*;
 import java.nio.*;
 import java.util.*;
 import java.util.zip.*;
@@ -41,35 +40,37 @@
  */
 public class FlaterTest extends Thread {
     private static final int DATA_LEN = 1024 * 128;
-    private static byte[] data;
+
+    private static ByteBuffer dataDirect;
+    private static ByteBuffer dataHeap;
 
     // If true, print extra info.
     private static final boolean debug = false;
 
     // Set of Flater threads running.
-    private static Set flaters =
-        Collections.synchronizedSet(new HashSet());
+    private static Set<Flater> flaters =
+        Collections.synchronizedSet(new HashSet<>());
 
     /** Fill in {@code data} with random values. */
     static void createData() {
-        ByteBuffer bb = ByteBuffer.allocate(8);
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        for (int i = 0; i < DATA_LEN; i++) {
-            bb.putDouble(0, Math.random());
-            baos.write(bb.array(), 0, 8);
+        ByteBuffer bb = ByteBuffer.allocateDirect(DATA_LEN * 8);
+        for (int i = 0; i < DATA_LEN * 8; i += 8) {
+            bb.putDouble(i, Math.random());
         }
-        data = baos.toByteArray();
-        if (debug) System.out.println("data length is " + data.length);
+        dataDirect = bb;
+        final ByteBuffer hb = ByteBuffer.allocate(bb.capacity());
+        hb.duplicate().put(bb.duplicate());
+        dataHeap = hb;
+        if (debug) System.out.println("data length is " + bb.capacity());
     }
 
     /** @return the length of the deflated {@code data}. */
-    private static int getDeflatedLength() throws Throwable {
-        int rc = 0;
+    private static int getDeflatedLength() {
         Deflater deflater = new Deflater();
-        deflater.setInput(data);
+        deflater.setInput(dataDirect.duplicate());
         deflater.finish();
-        byte[] out = new byte[data.length];
-        rc = deflater.deflate(out);
+        byte[] out = new byte[dataDirect.capacity()];
+        int rc = deflater.deflate(out);
         deflater.end();
         if (debug) System.out.println("deflatedLength is " + rc);
         return rc;
@@ -78,70 +79,98 @@
     /** Compares given bytes with those in {@code data}.
      * @throws Exception if given bytes don't match {@code data}.
      */
-    private static void validate(byte[] buf, int offset, int len) throws Exception {
+    private static void validate(ByteBuffer buf, int offset, int len) throws Exception {
         for (int i = 0; i < len; i++ ) {
-            if (buf[i] != data[offset+i]) {
+            if (buf.get(i) != dataDirect.get(offset+i)) {
                 throw new Exception("mismatch at " + (offset + i));
             }
         }
     }
 
-    public static void realMain(String[] args) throws Throwable {
+    public static void realMain(String[] args) {
+        int numThreads = args.length > 0 ? Integer.parseInt(args[0]) : 5;
         createData();
-        int numThreads = args.length > 0 ? Integer.parseInt(args[0]) : 5;
-        new FlaterTest().go(numThreads);
+        for (int srcMode = 0; srcMode <= 2; srcMode ++) {
+            for (int dstMode = 0; dstMode <= 2; dstMode ++) {
+                new FlaterTest().go(numThreads, srcMode, dstMode);
+            }
+        }
     }
 
-    private synchronized void go(int numThreads) throws Throwable {
+    private synchronized void go(int numThreads, int srcMode, int dstMode) {
         int deflatedLength = getDeflatedLength();
 
         long time = System.currentTimeMillis();
         for (int i = 0; i < numThreads; i++) {
-            Flater f = new Flater(deflatedLength);
+            Flater f = new Flater(deflatedLength, srcMode, dstMode);
             flaters.add(f);
             f.start();
         }
-        while (flaters.size() != 0) {
-            try {
-                Thread.currentThread().sleep(10);
-            } catch (InterruptedException ex) {
-                unexpected(ex);
+        synchronized (flaters) {
+            while (flaters.size() != 0) {
+                try {
+                    flaters.wait();
+                } catch (InterruptedException ex) {
+                    unexpected(ex);
+                }
             }
         }
         time = System.currentTimeMillis() - time;
         System.out.println("Time needed for " + numThreads
-                           + " threads to deflate/inflate: " + time + " ms.");
+                           + " threads to deflate/inflate: " + time + " ms (srcMode="+srcMode+",dstMode="+dstMode+")");
     }
 
     /** Deflates and inflates data. */
     static class Flater extends Thread {
         private final int deflatedLength;
+        private final int srcMode, dstMode;
 
-        private Flater(int length) {
+        private Flater(int length, int srcMode, int dstMode) {
             this.deflatedLength = length;
+            this.srcMode = srcMode;
+            this.dstMode = dstMode;
         }
 
         /** Deflates and inflates {@code data}. */
         public void run() {
             if (debug) System.out.println(getName() + " starting run()");
             try {
-                byte[] deflated = DeflateData(deflatedLength);
+                ByteBuffer deflated = DeflateData(deflatedLength);
                 InflateData(deflated);
             } catch (Throwable t) {
                 t.printStackTrace();
                 fail(getName() + " failed");
             } finally {
-                flaters.remove(this);
+                synchronized (flaters) {
+                    flaters.remove(this);
+                    if (flaters.isEmpty()) {
+                        flaters.notifyAll();
+                    }
+                }
             }
         }
 
         /** Returns a copy of {@code data} in deflated form. */
-        private byte[] DeflateData(int length) throws Throwable {
+        private ByteBuffer DeflateData(int length) {
             Deflater deflater = new Deflater();
-            deflater.setInput(data);
+            if (srcMode == 0) {
+                deflater.setInput(dataHeap.array());
+            } else if (srcMode == 1) {
+                deflater.setInput(dataHeap.duplicate());
+            } else {
+                assert srcMode == 2;
+                deflater.setInput(dataDirect.duplicate());
+            }
             deflater.finish();
-            byte[] out = new byte[length];
-            deflater.deflate(out);
+            ByteBuffer out = dstMode == 2 ? ByteBuffer.allocateDirect(length) : ByteBuffer.allocate(length);
+            int deflated;
+            if (dstMode == 0) {
+                deflated = deflater.deflate(out.array(), 0, length);
+                out.position(deflated);
+            } else {
+                deflater.deflate(out);
+            }
+            out.flip();
             return out;
         }
 
@@ -149,14 +178,30 @@
          * inflation.
          * @throws Exception if inflated bytes don't match {@code data}.
          */
-        private void InflateData(byte[] bytes) throws Throwable {
+        private void InflateData(ByteBuffer bytes) throws Throwable {
             Inflater inflater = new Inflater();
-            inflater.setInput(bytes, 0, bytes.length);
+            if (dstMode == 0) {
+                inflater.setInput(bytes.array(), 0, bytes.remaining());
+            } else {
+                inflater.setInput(bytes);
+            }
+            if (inflater.getRemaining() == 0) {
+                throw new Exception("Nothing to inflate (bytes=" + bytes + ")");
+            }
             int len = 1024 * 8;
             int offset = 0;
+            ByteBuffer buf = srcMode == 2 ? ByteBuffer.allocateDirect(len) : ByteBuffer.allocate(len);
             while (inflater.getRemaining() > 0) {
-                byte[] buf = new byte[len];
-                int inflated = inflater.inflate(buf, 0, len);
+                buf.clear();
+                int inflated;
+                if (srcMode == 0) {
+                    inflated = inflater.inflate(buf.array(), 0, buf.remaining());
+                } else {
+                    inflated = inflater.inflate(buf);
+                }
+                if (inflated == 0) {
+                    throw new Exception("Nothing inflated (dst=" + buf + ",offset=" + offset + ",rem=" + inflater.getRemaining() + ",srcMode="+srcMode+",dstMode="+dstMode+")");
+                }
                 validate(buf, offset, inflated);
                 offset += inflated;
             }