changeset 49316:73da889306b7

Merge
author prr
date Fri, 23 Mar 2018 11:14:43 -0700
parents 2d4964bc055d 49e0f711bb2b
children 2c3b9dbba7bc f46bfa7a2956
files make/mapfiles/libjsoundalsa/mapfile-vers src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c src/java.base/linux/native/libnio/ch/EPollPort.c src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java src/java.base/macosx/native/libnio/ch/KQueueArrayWrapper.c src/java.base/macosx/native/libnio/ch/KQueuePort.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_CommonUtils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_CommonUtils.h src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiIn.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiOut.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiUtils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_MidiUtils.h src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCM.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCMUtils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_PCMUtils.h src/java.desktop/unix/native/libjsound/PLATFORM_API_BsdOS_ALSA_Ports.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.h src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.h src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h src/java.desktop/unix/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_PCM.c src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Ports.c src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Utils.c src/java.desktop/unix/native/libjsound/PLATFORM_API_SolarisOS_Utils.h test/jdk/java/nio/channels/DatagramChannel/SendToUnresolved.java
diffstat 125 files changed, 7115 insertions(+), 10858 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Mar 23 11:18:39 2018 +0530
+++ b/.hgtags	Fri Mar 23 11:14:43 2018 -0700
@@ -476,3 +476,4 @@
 1fd4d6068f54561cfc67d54fc9ca84af7212c4f8 jdk-11+3
 e59941f7247d451fa7df9eaef3fce0f492f8420c jdk-11+4
 d5c43e9f08fb9a7c74aae0d48daf17f2ad2afaef jdk-11+5
+3acb379b86725c47e7f33358cb22efa8752ae532 jdk-11+6
--- a/doc/testing.html	Fri Mar 23 11:18:39 2018 +0530
+++ b/doc/testing.html	Fri Mar 23 11:14:43 2018 -0700
@@ -40,7 +40,7 @@
 $ make run-test-jdk_lang JTREG="JOBS=8"
 $ make run-test TEST=jdk_lang
 $ make run-test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
-$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"
+$ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
 $ make run-test TEST="jtreg:hotspot/test:hotspot_gc hotspot/test/native_sanity/JniVersion.java"
 $ make exploded-run-test TEST=hotspot_tier1</code></pre>
 <h3 id="configuration">Configuration</h3>
@@ -77,8 +77,8 @@
 <h2 id="test-suite-control">Test suite control</h2>
 <p>It is possible to control various aspects of the test suites using make control variables.</p>
 <p>These variables use a keyword=value approach to allow multiple values to be set. So, for instance, <code>JTREG=&quot;JOBS=1;TIMEOUT=8&quot;</code> will set the JTReg concurrency level to 1 and the timeout factor to 8. This is equivalent to setting <code>JTREG_JOBS=1 JTREG_TIMEOUT=8</code>, but using the keyword format means that the <code>JTREG</code> variable is parsed and verified for correctness, so <code>JTREG=&quot;TMIEOUT=8&quot;</code> would give an error, while <code>JTREG_TMIEOUT=8</code> would just pass unnoticed.</p>
-<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG=&quot;...;...&quot;</code>. This will also make sure spaces are preserved, as in <code>JTREG=&quot;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug&quot;</code>.</p>
-<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
+<p>To separate multiple keyword=value pairs, use <code>;</code> (semicolon). Since the shell normally eats <code>;</code>, the recommended usage is to write the assignment inside qoutes, e.g. <code>JTREG=&quot;...;...&quot;</code>. This will also make sure spaces are preserved, as in <code>JTREG=&quot;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug&quot;</code>.</p>
+<p>(Other ways are possible, e.g. using backslash: <code>JTREG=JOBS=1\;TIMEOUT=8</code>. Also, as a special technique, the string <code>%20</code> will be replaced with space for certain options, e.g. <code>JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug</code>. This can be useful if you have layers of scripts and have trouble getting proper quoting of command line arguments through.)</p>
 <p>As far as possible, the names of the keywords have been standardized between test suites.</p>
 <h3 id="jtreg-keywords">JTReg keywords</h3>
 <h4 id="jobs">JOBS</h4>
--- a/doc/testing.md	Fri Mar 23 11:18:39 2018 +0530
+++ b/doc/testing.md	Fri Mar 23 11:14:43 2018 -0700
@@ -18,7 +18,7 @@
     $ make run-test-jdk_lang JTREG="JOBS=8"
     $ make run-test TEST=jdk_lang
     $ make run-test-only TEST="gtest:LogTagSet gtest:LogTagSetDescriptions" GTEST="REPEAT=-1"
-    $ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"
+    $ make run-test TEST="hotspot/test:hotspot_gc" JTREG="JOBS=1;TIMEOUT=8;VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"
     $ make run-test TEST="jtreg:hotspot/test:hotspot_gc hotspot/test/native_sanity/JniVersion.java"
     $ make exploded-run-test TEST=hotspot_tier1
 
@@ -140,11 +140,11 @@
 To separate multiple keyword=value pairs, use `;` (semicolon). Since the shell
 normally eats `;`, the recommended usage is to write the assignment inside
 qoutes, e.g. `JTREG="...;..."`. This will also make sure spaces are preserved,
-as in `JTREG="VM_OTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
+as in `JTREG="VM_OPTIONS=-XshowSettings -Xlog:gc+ref=debug"`.
 
 (Other ways are possible, e.g. using backslash: `JTREG=JOBS=1\;TIMEOUT=8`.
 Also, as a special technique, the string `%20` will be replaced with space for
-certain options, e.g. `JTREG=VM_OTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
+certain options, e.g. `JTREG=VM_OPTIONS=-XshowSettings%20-Xlog:gc+ref=debug`.
 This can be useful if you have layers of scripts and have trouble getting
 proper quoting of command line arguments through.)
 
--- a/make/lib/SoundLibraries.gmk	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/lib/SoundLibraries.gmk	Fri Mar 23 11:14:43 2018 -0700
@@ -23,101 +23,50 @@
 # questions.
 #
 
-LIBJSOUND_SRC_DIRS := \
+LIBJSOUND_SRC_DIRS := $(wildcard \
     $(TOPDIR)/src/java.desktop/share/native/libjsound \
-    $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_TYPE)/native/libjsound \
-    #
+    $(TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libjsound \
+    )
+
 LIBJSOUND_CFLAGS := \
     -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \
     $(LIBJAVA_HEADER_FLAGS) \
     $(foreach dir, $(LIBJSOUND_SRC_DIRS), -I$(dir)) \
+    -DUSE_PORTS=TRUE \
+    -DUSE_DAUDIO=TRUE \
     #
 
-LIBJSOUND_SRC_FILES := Utilities.c Platform.c
-
-EXTRA_SOUND_JNI_LIBS :=
-
-LIBJSOUND_MIDIFILES := \
-    MidiInDevice.c \
-    MidiInDeviceProvider.c \
-    MidiOutDevice.c \
-    MidiOutDeviceProvider.c \
-    PlatformMidi.c
-
-# files needed for ports
-LIBJSOUND_PORTFILES := \
-    PortMixerProvider.c \
-    PortMixer.c
-
-# files needed for direct audio
-LIBJSOUND_DAUDIOFILES := \
-    DirectAudioDeviceProvider.c \
-    DirectAudioDevice.c
+ifneq ($(OPENJDK_TARGET_OS), solaris)
+  LIBJSOUND_CFLAGS += \
+      -DUSE_PLATFORM_MIDI_OUT=TRUE \
+      -DUSE_PLATFORM_MIDI_IN=TRUE \
+      #
+endif
 
 ifeq ($(OPENJDK_TARGET_OS), windows)
-  EXTRA_SOUND_JNI_LIBS += jsoundds
-  LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS \
-      -DUSE_PLATFORM_MIDI_OUT=TRUE \
-      -DUSE_PLATFORM_MIDI_IN=TRUE \
-      -DUSE_PORTS=TRUE
-  LIBJSOUND_SRC_FILES += \
-      PLATFORM_API_WinOS_Charset_Util.cpp \
-      PLATFORM_API_WinOS_MidiIn.cpp \
-      PLATFORM_API_WinOS_MidiOut.c \
-      PLATFORM_API_WinOS_Util.c \
-      PLATFORM_API_WinOS_Ports.c
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
-endif # OPENJDK_TARGET_OS windows
+  LIBJSOUND_CFLAGS += -DX_PLATFORM=X_WINDOWS
+endif
 
 ifeq ($(OPENJDK_TARGET_OS), linux)
-  EXTRA_SOUND_JNI_LIBS += jsoundalsa
   LIBJSOUND_CFLAGS += -DX_PLATFORM=X_LINUX
-endif # OPENJDK_TARGET_OS linux
+endif
 
 ifeq ($(OPENJDK_TARGET_OS), aix)
   LIBJSOUND_CFLAGS += -DX_PLATFORM=X_AIX
-endif # OPENJDK_TARGET_OS aix
+endif
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
   LIBJSOUND_TOOLCHAIN := TOOLCHAIN_LINK_CXX
-  LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX \
-      -DUSE_PORTS=TRUE \
-      -DUSE_DAUDIO=TRUE \
-      -DUSE_PLATFORM_MIDI_OUT=TRUE \
-      -DUSE_PLATFORM_MIDI_IN=TRUE
-  LIBJSOUND_SRC_DIRS += $(TOPDIR)/src/java.desktop/macosx/native/libjsound
-  LIBJSOUND_SRC_FILES += \
-      PLATFORM_API_MacOSX_Utils.cpp \
-      PLATFORM_API_MacOSX_PCM.cpp \
-      PLATFORM_API_MacOSX_Ports.cpp \
-      PLATFORM_API_MacOSX_MidiIn.c \
-      PLATFORM_API_MacOSX_MidiOut.c \
-      PLATFORM_API_MacOSX_MidiUtils.c
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_DAUDIOFILES)
-endif # OPENJDK_TARGET_OS macosx
+  LIBJSOUND_CFLAGS += -DX_PLATFORM=X_MACOSX
+endif
 
 ifeq ($(OPENJDK_TARGET_OS), solaris)
-  LIBJSOUND_CFLAGS += -DX_PLATFORM=X_SOLARIS \
-      -DUSE_PORTS=TRUE \
-      -DUSE_DAUDIO=TRUE
-  LIBJSOUND_SRC_FILES += \
-      PLATFORM_API_SolarisOS_Utils.c \
-      PLATFORM_API_SolarisOS_Ports.c \
-      PLATFORM_API_SolarisOS_PCM.c
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_MIDIFILES)
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_PORTFILES)
-  LIBJSOUND_SRC_FILES += $(LIBJSOUND_DAUDIOFILES)
-endif # OPENJDK_TARGET_OS solaris
-
-LIBJSOUND_CFLAGS += -DEXTRA_SOUND_JNI_LIBS='"$(EXTRA_SOUND_JNI_LIBS)"'
+  LIBJSOUND_CFLAGS += -DX_PLATFORM=X_SOLARIS
+endif
 
 $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUND, \
     NAME := jsound, \
     SRC := $(LIBJSOUND_SRC_DIRS), \
-    INCLUDE_FILES := $(LIBJSOUND_SRC_FILES), \
     TOOLCHAIN := $(LIBJSOUND_TOOLCHAIN), \
     OPTIMIZATION := LOW, \
     CFLAGS := $(CFLAGS_JDKLIB) \
@@ -127,10 +76,11 @@
     LDFLAGS := $(LDFLAGS_JDKLIB) \
         $(call SET_SHARED_LIBRARY_ORIGIN), \
     LIBS_unix := -ljava -ljvm, \
+    LIBS_linux := $(ALSA_LIBS), \
     LIBS_macosx := -framework CoreAudio -framework CoreFoundation \
-        -framework CoreServices -framework AudioUnit $(LIBCXX) \
-        -framework CoreMIDI -framework AudioToolbox, \
-    LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib winmm.lib, \
+        -framework CoreServices -framework AudioUnit \
+        -framework CoreMIDI -framework AudioToolbox $(LIBCXX), \
+    LIBS_windows := $(WIN_JAVA_LIB) advapi32.lib dsound.lib winmm.lib user32.lib ole32.lib, \
 ))
 
 $(BUILD_LIBJSOUND): $(call FindLib, java.base, java)
@@ -138,61 +88,3 @@
 TARGETS += $(BUILD_LIBJSOUND)
 
 ##########################################################################################
-
-ifneq ($(filter jsoundalsa, $(EXTRA_SOUND_JNI_LIBS)), )
-
-  $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUNDALSA, \
-      NAME := jsoundalsa, \
-      SRC := $(LIBJSOUND_SRC_DIRS), \
-      INCLUDE_FILES := Utilities.c $(LIBJSOUND_MIDIFILES) $(LIBJSOUND_PORTFILES) \
-          $(LIBJSOUND_DAUDIOFILES) \
-          PLATFORM_API_LinuxOS_ALSA_CommonUtils.c \
-          PLATFORM_API_LinuxOS_ALSA_PCM.c \
-          PLATFORM_API_LinuxOS_ALSA_PCMUtils.c \
-          PLATFORM_API_LinuxOS_ALSA_MidiIn.c \
-          PLATFORM_API_LinuxOS_ALSA_MidiOut.c \
-          PLATFORM_API_LinuxOS_ALSA_MidiUtils.c \
-          PLATFORM_API_LinuxOS_ALSA_Ports.c, \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CFLAGS_JDKLIB) $(ALSA_CFLAGS) \
-          $(LIBJSOUND_CFLAGS) \
-          -DUSE_DAUDIO=TRUE \
-          -DUSE_PORTS=TRUE \
-          -DUSE_PLATFORM_MIDI_OUT=TRUE \
-          -DUSE_PLATFORM_MIDI_IN=TRUE, \
-      MAPFILE := $(TOPDIR)/make/mapfiles/libjsoundalsa/mapfile-vers, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) \
-          $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LIBS := $(ALSA_LIBS) -ljava -ljvm, \
-  ))
-
-  $(BUILD_LIBJSOUNDALSA): $(call FindLib, java.base, java)
-
-  TARGETS += $(BUILD_LIBJSOUNDALSA)
-
-endif
-
-##########################################################################################
-
-ifneq ($(filter jsoundds, $(EXTRA_SOUND_JNI_LIBS)), )
-
-  $(eval $(call SetupJdkLibrary, BUILD_LIBJSOUNDDS, \
-      NAME := jsoundds, \
-      SRC := $(LIBJSOUND_SRC_DIRS), \
-      INCLUDE_FILES := Utilities.c $(LIBJSOUND_DAUDIOFILES) \
-          PLATFORM_API_WinOS_Charset_Util.cpp \
-          PLATFORM_API_WinOS_DirectSound.cpp, \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CFLAGS_JDKLIB) \
-          $(LIBJSOUND_CFLAGS) \
-          -DUSE_DAUDIO=TRUE, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
-          $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LIBS := $(JDKLIB_LIBS) dsound.lib winmm.lib user32.lib ole32.lib, \
-  ))
-
-  $(BUILD_LIBJSOUNDDS): $(call FindLib, java.base, java)
-
-  TARGETS += $(BUILD_LIBJSOUNDDS)
-
-endif
--- a/make/mapfiles/libjsound/mapfile-vers	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/mapfiles/libjsound/mapfile-vers	Fri Mar 23 11:14:43 2018 -0700
@@ -65,8 +65,6 @@
 		Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices;
 		Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor;
 		Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion;
-		Java_com_sun_media_sound_Platform_nGetExtraLibraries;
-		Java_com_sun_media_sound_Platform_nGetLibraryForFeature;
 		Java_com_sun_media_sound_Platform_nIsBigEndian;
 		Java_com_sun_media_sound_PortMixer_nClose;
 		Java_com_sun_media_sound_PortMixer_nControlGetFloatValue;
--- a/make/mapfiles/libjsoundalsa/mapfile-vers	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,82 +0,0 @@
-#
-# Copyright (c) 2005, 2013, 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.
-#
-
-# Define library interface.
-
-SUNWprivate_1.1 {
-    global:
-        Java_com_sun_media_sound_DirectAudioDeviceProvider_nGetNumDevices;
-        Java_com_sun_media_sound_DirectAudioDeviceProvider_nNewDirectAudioDeviceInfo;
-        Java_com_sun_media_sound_DirectAudioDevice_nAvailable;
-        Java_com_sun_media_sound_DirectAudioDevice_nClose;
-        Java_com_sun_media_sound_DirectAudioDevice_nFlush;
-        Java_com_sun_media_sound_DirectAudioDevice_nGetBufferSize;
-        Java_com_sun_media_sound_DirectAudioDevice_nGetBytePosition;
-        Java_com_sun_media_sound_DirectAudioDevice_nGetFormats;
-        Java_com_sun_media_sound_DirectAudioDevice_nIsStillDraining;
-        Java_com_sun_media_sound_DirectAudioDevice_nOpen;
-        Java_com_sun_media_sound_DirectAudioDevice_nRead;
-        Java_com_sun_media_sound_DirectAudioDevice_nRequiresServicing;
-        Java_com_sun_media_sound_DirectAudioDevice_nService;
-        Java_com_sun_media_sound_DirectAudioDevice_nSetBytePosition;
-        Java_com_sun_media_sound_DirectAudioDevice_nStart;
-        Java_com_sun_media_sound_DirectAudioDevice_nStop;
-        Java_com_sun_media_sound_DirectAudioDevice_nWrite;
-        Java_com_sun_media_sound_MidiInDeviceProvider_nGetDescription;
-        Java_com_sun_media_sound_MidiInDeviceProvider_nGetName;
-        Java_com_sun_media_sound_MidiInDeviceProvider_nGetNumDevices;
-        Java_com_sun_media_sound_MidiInDeviceProvider_nGetVendor;
-        Java_com_sun_media_sound_MidiInDeviceProvider_nGetVersion;
-        Java_com_sun_media_sound_MidiInDevice_nClose;
-        Java_com_sun_media_sound_MidiInDevice_nGetMessages;
-        Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp;
-        Java_com_sun_media_sound_MidiInDevice_nOpen;
-        Java_com_sun_media_sound_MidiInDevice_nStart;
-        Java_com_sun_media_sound_MidiInDevice_nStop;
-        Java_com_sun_media_sound_MidiOutDeviceProvider_nGetDescription;
-        Java_com_sun_media_sound_MidiOutDeviceProvider_nGetName;
-        Java_com_sun_media_sound_MidiOutDeviceProvider_nGetNumDevices;
-        Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVendor;
-        Java_com_sun_media_sound_MidiOutDeviceProvider_nGetVersion;
-        Java_com_sun_media_sound_MidiOutDevice_nClose;
-        Java_com_sun_media_sound_MidiOutDevice_nGetTimeStamp;
-        Java_com_sun_media_sound_MidiOutDevice_nOpen;
-        Java_com_sun_media_sound_MidiOutDevice_nSendLongMessage;
-        Java_com_sun_media_sound_MidiOutDevice_nSendShortMessage;
-        Java_com_sun_media_sound_PortMixerProvider_nGetNumDevices;
-        Java_com_sun_media_sound_PortMixerProvider_nNewPortMixerInfo;
-        Java_com_sun_media_sound_PortMixer_nClose;
-        Java_com_sun_media_sound_PortMixer_nControlGetFloatValue;
-        Java_com_sun_media_sound_PortMixer_nControlGetIntValue;
-        Java_com_sun_media_sound_PortMixer_nControlSetFloatValue;
-        Java_com_sun_media_sound_PortMixer_nControlSetIntValue;
-        Java_com_sun_media_sound_PortMixer_nGetControls;
-        Java_com_sun_media_sound_PortMixer_nGetPortCount;
-        Java_com_sun_media_sound_PortMixer_nGetPortName;
-        Java_com_sun_media_sound_PortMixer_nGetPortType;
-        Java_com_sun_media_sound_PortMixer_nOpen;
-    local:
-        *;
-};
--- a/make/mapfiles/libnio/mapfile-linux	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/mapfiles/libnio/mapfile-linux	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 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
@@ -37,23 +37,12 @@
                 Java_sun_nio_ch_DatagramDispatcher_readv0;
                 Java_sun_nio_ch_DatagramDispatcher_write0;
                 Java_sun_nio_ch_DatagramDispatcher_writev0;
-                Java_sun_nio_ch_EPollArrayWrapper_epollCreate;
-                Java_sun_nio_ch_EPollArrayWrapper_epollCtl;
-                Java_sun_nio_ch_EPollArrayWrapper_epollWait;
-		Java_sun_nio_ch_EPollArrayWrapper_init;
-		Java_sun_nio_ch_EPollArrayWrapper_interrupt;
-		Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
-		Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
 		Java_sun_nio_ch_EPoll_eventSize;
 		Java_sun_nio_ch_EPoll_eventsOffset;
 		Java_sun_nio_ch_EPoll_dataOffset;
-		Java_sun_nio_ch_EPoll_epollCreate;
-		Java_sun_nio_ch_EPoll_epollCtl;
-		Java_sun_nio_ch_EPoll_epollWait;
-		Java_sun_nio_ch_EPollPort_close0;
-		Java_sun_nio_ch_EPollPort_drain1;
-		Java_sun_nio_ch_EPollPort_interrupt;
-		Java_sun_nio_ch_EPollPort_socketpair;
+		Java_sun_nio_ch_EPoll_create;
+		Java_sun_nio_ch_EPoll_ctl;
+		Java_sun_nio_ch_EPoll_wait;
                 Java_sun_nio_ch_FileChannelImpl_initIDs;
                 Java_sun_nio_ch_FileChannelImpl_map0;
                 Java_sun_nio_ch_FileChannelImpl_position0;
@@ -95,6 +84,7 @@
                 Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
+                Java_sun_nio_ch_IOUtil_write1;
 		Java_sun_nio_ch_NativeThread_current;
 		Java_sun_nio_ch_NativeThread_init;
 		Java_sun_nio_ch_NativeThread_signal;
--- a/make/mapfiles/libnio/mapfile-macosx	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/mapfiles/libnio/mapfile-macosx	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 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,7 +42,7 @@
                 Java_sun_nio_ch_FileChannelImpl_position0;
                 Java_sun_nio_ch_FileChannelImpl_transferTo0;
                 Java_sun_nio_ch_FileChannelImpl_unmap0;
-		Java_sun_nio_ch_FileDispatcherImpl_allocate0;
+	        Java_sun_nio_ch_FileDispatcherImpl_allocate0;
                 Java_sun_nio_ch_FileDispatcherImpl_close0;
                 Java_sun_nio_ch_FileDispatcherImpl_closeIntFD;
 		Java_sun_nio_ch_FileDispatcherImpl_force0;
@@ -71,117 +71,115 @@
                 Java_sun_nio_ch_IOUtil_configureBlocking;
                 Java_sun_nio_ch_IOUtil_drain;
                 Java_sun_nio_ch_IOUtil_fdVal;
+                Java_sun_nio_ch_IOUtil_fdLimit;
                 Java_sun_nio_ch_IOUtil_initIDs;
+                Java_sun_nio_ch_IOUtil_iovMax;
                 Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
-                Java_sun_nio_ch_IOUtil_iovMax;
-		Java_sun_nio_ch_KQueue_kqueue;
-		Java_sun_nio_ch_KQueue_keventRegister;
-		Java_sun_nio_ch_KQueue_keventPoll;
-		Java_sun_nio_ch_KQueue_keventSize;
-		Java_sun_nio_ch_KQueue_identOffset;
-		Java_sun_nio_ch_KQueue_filterOffset;
-		Java_sun_nio_ch_KQueue_flagsOffset;
-		Java_sun_nio_ch_KQueuePort_socketpair;
-		Java_sun_nio_ch_KQueuePort_interrupt;
-		Java_sun_nio_ch_KQueuePort_drain1;
-		Java_sun_nio_ch_KQueuePort_close0;
-		Java_sun_nio_ch_NativeThread_current;
-		Java_sun_nio_ch_NativeThread_init;
-		Java_sun_nio_ch_NativeThread_signal;
-		Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0;
-		Java_sun_nio_ch_Net_canJoin6WithIPv4Group0;
-		Java_sun_nio_ch_Net_socket0;
-		Java_sun_nio_ch_Net_bind0;
-		Java_sun_nio_ch_Net_connect0;
-		Java_sun_nio_ch_Net_listen;
-		Java_sun_nio_ch_Net_localPort;
-		Java_sun_nio_ch_Net_localInetAddress;
-		Java_sun_nio_ch_Net_getIntOption0;
-		Java_sun_nio_ch_Net_setIntOption0;
+                Java_sun_nio_ch_IOUtil_write1;
+                Java_sun_nio_ch_KQueue_create;
+                Java_sun_nio_ch_KQueue_register;
+                Java_sun_nio_ch_KQueue_poll;
+                Java_sun_nio_ch_KQueue_keventSize;
+                Java_sun_nio_ch_KQueue_identOffset;
+                Java_sun_nio_ch_KQueue_filterOffset;
+                Java_sun_nio_ch_KQueue_flagsOffset;
+                Java_sun_nio_ch_NativeThread_current;
+                Java_sun_nio_ch_NativeThread_init;
+                Java_sun_nio_ch_NativeThread_signal;
+                Java_sun_nio_ch_Net_canIPv6SocketJoinIPv4Group0;
+                Java_sun_nio_ch_Net_canJoin6WithIPv4Group0;
+                Java_sun_nio_ch_Net_socket0;
+                Java_sun_nio_ch_Net_bind0;
+                Java_sun_nio_ch_Net_connect0;
+                Java_sun_nio_ch_Net_listen;
+                Java_sun_nio_ch_Net_localPort;
+                Java_sun_nio_ch_Net_localInetAddress;
+                Java_sun_nio_ch_Net_getIntOption0;
+                Java_sun_nio_ch_Net_setIntOption0;
                 Java_sun_nio_ch_Net_initIDs;
 		Java_sun_nio_ch_Net_isIPv6Available0;
                 Java_sun_nio_ch_Net_isReusePortAvailable0;
-		Java_sun_nio_ch_Net_joinOrDrop4;
-		Java_sun_nio_ch_Net_blockOrUnblock4;
-		Java_sun_nio_ch_Net_joinOrDrop6;
-		Java_sun_nio_ch_Net_blockOrUnblock6;
-		Java_sun_nio_ch_Net_setInterface4;
-		Java_sun_nio_ch_Net_getInterface4;
-		Java_sun_nio_ch_Net_setInterface6;
-		Java_sun_nio_ch_Net_getInterface6;
-		Java_sun_nio_ch_Net_shutdown;
-		Java_sun_nio_ch_Net_poll;
-		Java_sun_nio_ch_Net_pollinValue;
-		Java_sun_nio_ch_Net_polloutValue;
-		Java_sun_nio_ch_Net_pollerrValue;
-		Java_sun_nio_ch_Net_pollhupValue;
-		Java_sun_nio_ch_Net_pollnvalValue;
-		Java_sun_nio_ch_Net_pollconnValue;
+                Java_sun_nio_ch_Net_joinOrDrop4;
+                Java_sun_nio_ch_Net_blockOrUnblock4;
+                Java_sun_nio_ch_Net_joinOrDrop6;
+                Java_sun_nio_ch_Net_blockOrUnblock6;
+                Java_sun_nio_ch_Net_setInterface4;
+                Java_sun_nio_ch_Net_getInterface4;
+                Java_sun_nio_ch_Net_setInterface6;
+                Java_sun_nio_ch_Net_getInterface6;
+                Java_sun_nio_ch_Net_shutdown;
+                Java_sun_nio_ch_Net_poll;
+                Java_sun_nio_ch_Net_pollinValue;
+                Java_sun_nio_ch_Net_polloutValue;
+                Java_sun_nio_ch_Net_pollerrValue;
+                Java_sun_nio_ch_Net_pollhupValue;
+                Java_sun_nio_ch_Net_pollnvalValue;
+                Java_sun_nio_ch_Net_pollconnValue;
                 Java_sun_nio_ch_Net_isExclusiveBindAvailable;
                 Java_sun_nio_ch_PollArrayWrapper_interrupt;
                 Java_sun_nio_ch_PollArrayWrapper_poll0;
                 Java_sun_nio_ch_ServerSocketChannelImpl_accept0;
                 Java_sun_nio_ch_ServerSocketChannelImpl_initIDs;
                 Java_sun_nio_ch_SocketChannelImpl_checkConnect;
-		Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
-		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
-		Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
-		Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
-		Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
-		Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
-		Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
-		Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
-		Java_sun_nio_fs_UnixNativeDispatcher_init;
-		Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
-		Java_sun_nio_fs_UnixNativeDispatcher_strerror;
-		Java_sun_nio_fs_UnixNativeDispatcher_dup;
-		Java_sun_nio_fs_UnixNativeDispatcher_access0;
-		Java_sun_nio_fs_UnixNativeDispatcher_exists0;
-		Java_sun_nio_fs_UnixNativeDispatcher_stat0;
+                Java_sun_nio_ch_SocketChannelImpl_sendOutOfBandData;
+                Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_accept0;
+                Java_sun_nio_ch_UnixAsynchronousServerSocketChannelImpl_initIDs;
+                Java_sun_nio_ch_UnixAsynchronousSocketChannelImpl_checkConnect;
+                Java_sun_nio_fs_BsdNativeDispatcher_initIDs;
+                Java_sun_nio_fs_BsdNativeDispatcher_getfsstat;
+                Java_sun_nio_fs_BsdNativeDispatcher_fsstatEntry;
+                Java_sun_nio_fs_BsdNativeDispatcher_endfsstat;
+                Java_sun_nio_fs_UnixNativeDispatcher_init;
+                Java_sun_nio_fs_UnixNativeDispatcher_getcwd;
+                Java_sun_nio_fs_UnixNativeDispatcher_strerror;
+                Java_sun_nio_fs_UnixNativeDispatcher_dup;
+                Java_sun_nio_fs_UnixNativeDispatcher_access0;
+                Java_sun_nio_fs_UnixNativeDispatcher_exists0;
+                Java_sun_nio_fs_UnixNativeDispatcher_stat0;
                 Java_sun_nio_fs_UnixNativeDispatcher_stat1;
-		Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
-		Java_sun_nio_fs_UnixNativeDispatcher_fstat;
-		Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
-		Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
-		Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
-		Java_sun_nio_fs_UnixNativeDispatcher_chown0;
-		Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
-		Java_sun_nio_fs_UnixNativeDispatcher_fchown;
-		Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
-		Java_sun_nio_fs_UnixNativeDispatcher_futimes;
-		Java_sun_nio_fs_UnixNativeDispatcher_open0;
-		Java_sun_nio_fs_UnixNativeDispatcher_openat0;
-		Java_sun_nio_fs_UnixNativeDispatcher_close0;
-		Java_sun_nio_fs_UnixNativeDispatcher_read;
-		Java_sun_nio_fs_UnixNativeDispatcher_write;
-		Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
-		Java_sun_nio_fs_UnixNativeDispatcher_fclose;
-		Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
-		Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
-		Java_sun_nio_fs_UnixNativeDispatcher_readdir;
-		Java_sun_nio_fs_UnixNativeDispatcher_closedir;
-		Java_sun_nio_fs_UnixNativeDispatcher_link0;
-		Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
-		Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
-		Java_sun_nio_fs_UnixNativeDispatcher_rename0;
-		Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
-		Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
-		Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
-		Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
-		Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
-		Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
-		Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
-		Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
-		Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
-		Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
-		Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
-		Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
-		Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
-		Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
-		Java_sun_nio_fs_UnixCopyFile_transfer;
-		handleSocketError;
+                Java_sun_nio_fs_UnixNativeDispatcher_lstat0;
+                Java_sun_nio_fs_UnixNativeDispatcher_fstat;
+                Java_sun_nio_fs_UnixNativeDispatcher_fstatat0;
+                Java_sun_nio_fs_UnixNativeDispatcher_chmod0;
+                Java_sun_nio_fs_UnixNativeDispatcher_fchmod;
+                Java_sun_nio_fs_UnixNativeDispatcher_chown0;
+                Java_sun_nio_fs_UnixNativeDispatcher_lchown0;
+                Java_sun_nio_fs_UnixNativeDispatcher_fchown;
+                Java_sun_nio_fs_UnixNativeDispatcher_utimes0;
+                Java_sun_nio_fs_UnixNativeDispatcher_futimes;
+                Java_sun_nio_fs_UnixNativeDispatcher_open0;
+                Java_sun_nio_fs_UnixNativeDispatcher_openat0;
+                Java_sun_nio_fs_UnixNativeDispatcher_close0;
+                Java_sun_nio_fs_UnixNativeDispatcher_read;
+                Java_sun_nio_fs_UnixNativeDispatcher_write;
+                Java_sun_nio_fs_UnixNativeDispatcher_fopen0;
+                Java_sun_nio_fs_UnixNativeDispatcher_fclose;
+                Java_sun_nio_fs_UnixNativeDispatcher_opendir0;
+                Java_sun_nio_fs_UnixNativeDispatcher_fdopendir;
+                Java_sun_nio_fs_UnixNativeDispatcher_readdir;
+                Java_sun_nio_fs_UnixNativeDispatcher_closedir;
+                Java_sun_nio_fs_UnixNativeDispatcher_link0;
+                Java_sun_nio_fs_UnixNativeDispatcher_unlink0;
+                Java_sun_nio_fs_UnixNativeDispatcher_unlinkat0;
+                Java_sun_nio_fs_UnixNativeDispatcher_rename0;
+                Java_sun_nio_fs_UnixNativeDispatcher_renameat0;
+                Java_sun_nio_fs_UnixNativeDispatcher_mkdir0;
+                Java_sun_nio_fs_UnixNativeDispatcher_rmdir0;
+                Java_sun_nio_fs_UnixNativeDispatcher_symlink0;
+                Java_sun_nio_fs_UnixNativeDispatcher_readlink0;
+                Java_sun_nio_fs_UnixNativeDispatcher_realpath0;
+                Java_sun_nio_fs_UnixNativeDispatcher_statvfs0;
+                Java_sun_nio_fs_UnixNativeDispatcher_pathconf0;
+                Java_sun_nio_fs_UnixNativeDispatcher_fpathconf;
+                Java_sun_nio_fs_UnixNativeDispatcher_mknod0;
+                Java_sun_nio_fs_UnixNativeDispatcher_getpwuid;
+                Java_sun_nio_fs_UnixNativeDispatcher_getgrgid;
+                Java_sun_nio_fs_UnixNativeDispatcher_getpwnam0;
+                Java_sun_nio_fs_UnixNativeDispatcher_getgrnam0;
+                Java_sun_nio_fs_UnixCopyFile_transfer;
+                handleSocketError;
 
 	local:
 		*;
--- a/make/mapfiles/libnio/mapfile-solaris	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/mapfiles/libnio/mapfile-solaris	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2001, 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,7 +38,6 @@
                 Java_sun_nio_ch_DatagramDispatcher_write0;
                 Java_sun_nio_ch_DatagramDispatcher_writev0;
                 Java_sun_nio_ch_DevPollArrayWrapper_init;
-                Java_sun_nio_ch_DevPollArrayWrapper_interrupt;
                 Java_sun_nio_ch_DevPollArrayWrapper_poll0;
                 Java_sun_nio_ch_DevPollArrayWrapper_register;
                 Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple;
@@ -83,6 +82,7 @@
                 Java_sun_nio_ch_IOUtil_makePipe;
                 Java_sun_nio_ch_IOUtil_randomBytes;
                 Java_sun_nio_ch_IOUtil_setfdVal;
+                Java_sun_nio_ch_IOUtil_write1;
 		Java_sun_nio_ch_NativeThread_current;
 		Java_sun_nio_ch_NativeThread_init;
 		Java_sun_nio_ch_NativeThread_signal;
--- a/make/scripts/compare.sh	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/scripts/compare.sh	Fri Mar 23 11:14:43 2018 -0700
@@ -1298,22 +1298,37 @@
     # Find the common images to compare, prioritizing later build stages
     if [ -d "$THIS/install/jdk" ] && [ -d "$OTHER/install/jdk" ]; then
         THIS_JDK="$THIS/install/jdk"
-        THIS_JRE="$THIS/install/jre"
         OTHER_JDK="$OTHER/install/jdk"
-        OTHER_JRE="$OTHER/install/jre"
-        echo "Selecting install images for compare"
+        echo "Selecting install images for JDK compare"
+        if [ -d "$THIS/install/jre" ] && [ -d "$OTHER/install/jre" ]; then
+            THIS_JRE="$THIS/install/jre"
+            OTHER_JRE="$OTHER/install/jre"
+            echo "Also selecting install images for JRE compare"
+        else
+            echo "No install JRE image found"
+        fi
     elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/deploy/images/jdk" ]; then
         THIS_JDK="$THIS/images/jdk"
-        THIS_JRE="$THIS/images/jre"
         OTHER_JDK="$OTHER/deploy/images/jdk"
-        OTHER_JRE="$OTHER/deploy/images/jre"
-        echo "Selecting deploy images for compare"
+        echo "Selecting deploy images for JDK compare"
+        if [ -d "$THIS/images/jre" ] && [ -d "$OTHER/deploy/images/jre" ]; then
+            THIS_JRE="$THIS/images/jre"
+            OTHER_JRE="$OTHER/deploy/images/jre"
+            echo "Selecting deploy images for JRE compare"
+        else
+            echo "No deploy JRE image found"
+        fi
     elif [ -d "$THIS/images/jdk" ] && [ -d "$OTHER/images/jdk" ]; then
         THIS_JDK="$THIS/images/jdk"
-        THIS_JRE="$THIS/images/jre"
         OTHER_JDK="$OTHER/images/jdk"
-        OTHER_JRE="$OTHER/images/jre"
-        echo "Selecting jdk images for compare"
+        echo "Selecting normal images for JDK compare"
+        if [ -d "$THIS/images/jre" ] && [ -d "$OTHER/images/jre" ]; then
+            THIS_JRE="$THIS/images/jre"
+            OTHER_JRE="$OTHER/images/jre"
+            echo "Selecting normal images for JRE compare"
+        else
+            echo "No normal JRE image found"
+        fi
     elif [ -d "$(ls -d $THIS/licensee-src/build/*/images/jdk 2> /dev/null)" ] \
         && [ -d "$(ls -d $OTHER/licensee-src/build/*/images/jdk 2> /dev/null)" ]
     then
@@ -1406,9 +1421,11 @@
     else
         OTHER_SEC_DIR="$OTHER/tmp"
     fi
-    OTHER_SEC_BIN="$OTHER_SEC_DIR/sec-bin.zip"
-    THIS_SEC_DIR="$THIS/images"
-    THIS_SEC_BIN="$THIS_SEC_DIR/sec-bin.zip"
+    if [ -f "$THIS_SEC_DIR/sec-bin.zip" ]; then
+        OTHER_SEC_BIN="$OTHER_SEC_DIR/sec-bin.zip"
+        THIS_SEC_DIR="$THIS/images"
+        THIS_SEC_BIN="$THIS_SEC_DIR/sec-bin.zip"
+    fi
     if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
         if [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; then
             JGSS_WINDOWS_BIN="jgss-windows-x64-bin.zip"
@@ -1437,11 +1454,12 @@
     if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
         echo -n "JDK "
         compare_dirs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+        echo -n "JDK "
+        compare_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+    fi
+    if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
         echo -n "JRE "
         compare_dirs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
-
-        echo -n "JDK "
-        compare_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
         echo -n "JRE "
         compare_files $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
     fi
@@ -1480,49 +1498,38 @@
     fi
 fi
 
-if [ "$CMP_PERMS" = "true" ]; then
+if [ "$CMP_LIBS" = "true" ]; then
     if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
         echo -n "JDK "
-        compare_permissions $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
-        echo -n "JRE "
-        compare_permissions $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
+        compare_all_libs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
     fi
     if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
-        compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+        compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
     fi
     if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
         echo -n "JavaAppletPlugin "
-        compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+        compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
     fi
     if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
         echo -n "Sparkle.framework "
-        compare_permissions $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+        compare_all_libs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
     fi
 fi
 
-if [ "$CMP_TYPES" = "true" ]; then
+if [ "$CMP_EXECS" = "true" ]; then
     if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
-        echo -n "JDK "
-        compare_file_types $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
-        echo -n "JRE "
-        compare_file_types $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
-    fi
-    if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
-        echo -n "JDK Bundle "
-        compare_file_types $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
-        echo -n "JRE Bundle "
-        compare_file_types $THIS_JRE_BUNDLE $OTHER_JRE_BUNDLE $COMPARE_ROOT/jre-bundle
+        compare_all_execs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
     fi
     if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
-        compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+        compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
     fi
     if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
         echo -n "JavaAppletPlugin "
-        compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+        compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
     fi
     if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
         echo -n "Sparkle.framework "
-        compare_file_types $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+        compare_all_execs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
     fi
 fi
 
@@ -1530,6 +1537,8 @@
     if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
         echo -n "JDK "
         compare_general_files $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+    fi
+    if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
         echo -n "JRE "
         compare_general_files $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
     fi
@@ -1601,46 +1610,53 @@
     fi
 fi
 
-if [ "$CMP_LIBS" = "true" ]; then
+if [ "$CMP_PERMS" = "true" ]; then
     if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
         echo -n "JDK "
-        compare_all_libs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
-        if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
-            echo -n "JRE "
-            compare_all_libs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
-        fi
+        compare_permissions $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+    fi
+    if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
+        echo -n "JRE "
+        compare_permissions $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
     fi
     if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
-        compare_all_libs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+        compare_permissions $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
     fi
     if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
         echo -n "JavaAppletPlugin "
-        compare_all_libs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+        compare_permissions $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
     fi
     if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
         echo -n "Sparkle.framework "
-        compare_all_libs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+        compare_permissions $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
     fi
 fi
 
-if [ "$CMP_EXECS" = "true" ]; then
+if [ "$CMP_TYPES" = "true" ]; then
     if [ -n "$THIS_JDK" ] && [ -n "$OTHER_JDK" ]; then
-        compare_all_execs $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
-        if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
-            echo -n "JRE "
-            compare_all_execs $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
-        fi
+        echo -n "JDK "
+        compare_file_types $THIS_JDK $OTHER_JDK $COMPARE_ROOT/jdk
+    fi
+    if [ -n "$THIS_JRE" ] && [ -n "$OTHER_JRE" ]; then
+        echo -n "JRE "
+        compare_file_types $THIS_JRE $OTHER_JRE $COMPARE_ROOT/jre
+    fi
+    if [ -n "$THIS_JDK_BUNDLE" ] && [ -n "$OTHER_JDK_BUNDLE" ]; then
+        echo -n "JDK Bundle "
+        compare_file_types $THIS_JDK_BUNDLE $OTHER_JDK_BUNDLE $COMPARE_ROOT/jdk-bundle
+        echo -n "JRE Bundle "
+        compare_file_types $THIS_JRE_BUNDLE $OTHER_JRE_BUNDLE $COMPARE_ROOT/jre-bundle
     fi
     if [ -n "$THIS_BASE_DIR" ] && [ -n "$OTHER_BASE_DIR" ]; then
-        compare_all_execs $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
+        compare_file_types $THIS_BASE_DIR $OTHER_BASE_DIR $COMPARE_ROOT/base_dir
     fi
     if [ -n "$THIS_DEPLOY_APPLET_PLUGIN_DIR" ] && [ -n "$OTHER_DEPLOY_APPLET_PLUGIN_DIR" ]; then
         echo -n "JavaAppletPlugin "
-        compare_all_execs $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
+        compare_file_types $THIS_DEPLOY_APPLET_PLUGIN_DIR $OTHER_DEPLOY_APPLET_PLUGIN_DIR $COMPARE_ROOT/plugin
     fi
     if [ -n "$THIS_SPARKLE_DIR" ] && [ -n "$OTHER_SPARKLE_DIR" ]; then
         echo -n "Sparkle.framework "
-        compare_all_execs $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
+        compare_file_types $THIS_SPARKLE_DIR $OTHER_SPARKLE_DIR $COMPARE_ROOT/sparkle
     fi
 fi
 
--- a/make/scripts/compare_exceptions.sh.incl	Fri Mar 23 11:18:39 2018 +0530
+++ b/make/scripts/compare_exceptions.sh.incl	Fri Mar 23 11:14:43 2018 -0700
@@ -339,7 +339,7 @@
 
   DIS_DIFF_FILTER="$SED \
       -e 's/^[0-9a-f]\{16\}/<ADDR>:/' \
-      -e 's/^ *[0-9a-f]\{3,8\}:/  <ADDR>:/' \
+      -e 's/^ *[0-9a-f]\{3,12\}:/  <ADDR>:/' \
       -e 's/:	[0-9a-f][0-9a-f]\( [0-9a-f][0-9a-f]\)\{2,10\}/:	<NUMS>/' \
       -e 's/\$[a-zA-Z0-9_\$]\{15\}\./<SYM>./' \
       -e 's/, [0-9a-fx\-]\{1,8\}/, <ADDR>/g' \
--- a/src/java.base/linux/classes/sun/nio/ch/EPoll.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/linux/classes/sun/nio/ch/EPoll.java	Fri Mar 23 11:14:43 2018 -0700
@@ -109,11 +109,11 @@
 
     private static native int dataOffset();
 
-    static native int epollCreate() throws IOException;
+    static native int create() throws IOException;
 
-    static native int epollCtl(int epfd, int opcode, int fd, int events);
+    static native int ctl(int epfd, int opcode, int fd, int events);
 
-    static native int epollWait(int epfd, long pollAddress, int numfds)
+    static native int wait(int epfd, long pollAddress, int numfds, int timeout)
         throws IOException;
 
     static {
--- a/src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,309 +0,0 @@
-/*
- * 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
- * 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.ch;
-
-import java.io.IOException;
-import java.security.AccessController;
-import java.util.BitSet;
-import java.util.HashMap;
-import java.util.Map;
-import sun.security.action.GetIntegerAction;
-
-/**
- * Manipulates a native array of epoll_event structs on Linux:
- *
- * typedef union epoll_data {
- *     void *ptr;
- *     int fd;
- *     __uint32_t u32;
- *     __uint64_t u64;
- *  } epoll_data_t;
- *
- * struct epoll_event {
- *     __uint32_t events;
- *     epoll_data_t data;
- * };
- *
- * The system call to wait for I/O events is epoll_wait(2). It populates an
- * array of epoll_event structures that are passed to the call. The data
- * member of the epoll_event structure contains the same data as was set
- * when the file descriptor was registered to epoll via epoll_ctl(2). In
- * this implementation we set data.fd to be the file descriptor that we
- * register. That way, we have the file descriptor available when we
- * process the events.
- */
-
-class EPollArrayWrapper {
-    // EPOLL_EVENTS
-    private static final int EPOLLIN      = 0x001;
-
-    // opcodes
-    private static final int EPOLL_CTL_ADD      = 1;
-    private static final int EPOLL_CTL_DEL      = 2;
-    private static final int EPOLL_CTL_MOD      = 3;
-
-    // Miscellaneous constants
-    private static final int SIZE_EPOLLEVENT  = sizeofEPollEvent();
-    private static final int EVENT_OFFSET     = 0;
-    private static final int DATA_OFFSET      = offsetofData();
-    private static final int FD_OFFSET        = DATA_OFFSET;
-    private static final int OPEN_MAX         = IOUtil.fdLimit();
-    private static final int NUM_EPOLLEVENTS  = Math.min(OPEN_MAX, 8192);
-
-    // Special value to indicate that an update should be ignored
-    private static final byte  KILLED = (byte)-1;
-
-    // Initial size of arrays for fd registration changes
-    private static final int INITIAL_PENDING_UPDATE_SIZE = 64;
-
-    // maximum size of updatesLow
-    private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged(
-        new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024)));
-
-    // The fd of the epoll driver
-    private final int epfd;
-
-     // The epoll_event array for results from epoll_wait
-    private final AllocatedNativeObject pollArray;
-
-    // Base address of the epoll_event array
-    private final long pollArrayAddress;
-
-    // The fd of the interrupt line going out
-    private final int outgoingInterruptFD;
-
-    // Number of updated pollfd entries
-    private int updated;
-
-    // object to synchronize fd registration changes
-    private final Object updateLock = new Object();
-
-    // number of file descriptors with registration changes pending
-    private int updateCount;
-
-    // file descriptors with registration changes pending
-    private int[] updateDescriptors = new int[INITIAL_PENDING_UPDATE_SIZE];
-
-    // events for file descriptors with registration changes pending, indexed
-    // by file descriptor and stored as bytes for efficiency reasons. For
-    // file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
-    // least) then the update is stored in a map.
-    private final byte[] eventsLow = new byte[MAX_UPDATE_ARRAY_SIZE];
-    private final Map<Integer,Byte> eventsHigh = new HashMap<>();
-
-    // Used by release and updateRegistrations to track whether a file
-    // descriptor is registered with epoll.
-    private final BitSet registered = new BitSet();
-
-
-    EPollArrayWrapper(int fd0, int fd1) throws IOException {
-        // creates the epoll file descriptor
-        epfd = epollCreate();
-
-        // the epoll_event array passed to epoll_wait
-        int allocationSize = NUM_EPOLLEVENTS * SIZE_EPOLLEVENT;
-        pollArray = new AllocatedNativeObject(allocationSize, true);
-        pollArrayAddress = pollArray.address();
-
-        outgoingInterruptFD = fd1;
-        epollCtl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
-    }
-
-    void putEventOps(int i, int event) {
-        int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
-        pollArray.putInt(offset, event);
-    }
-
-    void putDescriptor(int i, int fd) {
-        int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
-        pollArray.putInt(offset, fd);
-    }
-
-    int getEventOps(int i) {
-        int offset = SIZE_EPOLLEVENT * i + EVENT_OFFSET;
-        return pollArray.getInt(offset);
-    }
-
-    int getDescriptor(int i) {
-        int offset = SIZE_EPOLLEVENT * i + FD_OFFSET;
-        return pollArray.getInt(offset);
-    }
-
-    /**
-     * Returns {@code true} if updates for the given key (file
-     * descriptor) are killed.
-     */
-    private boolean isEventsHighKilled(Integer key) {
-        assert key >= MAX_UPDATE_ARRAY_SIZE;
-        Byte value = eventsHigh.get(key);
-        return (value != null && value == KILLED);
-    }
-
-    /**
-     * Sets the pending update events for the given file descriptor. This
-     * method has no effect if the update events is already set to KILLED,
-     * unless {@code force} is {@code true}.
-     */
-    private void setUpdateEvents(int fd, byte events, boolean force) {
-        if (fd < MAX_UPDATE_ARRAY_SIZE) {
-            if ((eventsLow[fd] != KILLED) || force) {
-                eventsLow[fd] = events;
-            }
-        } else {
-            Integer key = Integer.valueOf(fd);
-            if (!isEventsHighKilled(key) || force) {
-                eventsHigh.put(key, Byte.valueOf(events));
-            }
-        }
-    }
-
-    /**
-     * Returns the pending update events for the given file descriptor.
-     */
-    private byte getUpdateEvents(int fd) {
-        if (fd < MAX_UPDATE_ARRAY_SIZE) {
-            return eventsLow[fd];
-        } else {
-            Byte result = eventsHigh.get(Integer.valueOf(fd));
-            // result should never be null
-            return result.byteValue();
-        }
-    }
-
-    /**
-     * Update the events for a given file descriptor
-     */
-    void setInterest(int fd, int mask) {
-        synchronized (updateLock) {
-            // record the file descriptor and events
-            int oldCapacity = updateDescriptors.length;
-            if (updateCount == oldCapacity) {
-                int newCapacity = oldCapacity + INITIAL_PENDING_UPDATE_SIZE;
-                int[] newDescriptors = new int[newCapacity];
-                System.arraycopy(updateDescriptors, 0, newDescriptors, 0, oldCapacity);
-                updateDescriptors = newDescriptors;
-            }
-            updateDescriptors[updateCount++] = fd;
-
-            // events are stored as bytes for efficiency reasons
-            byte b = (byte)mask;
-            assert (b == mask) && (b != KILLED);
-            setUpdateEvents(fd, b, false);
-        }
-    }
-
-    /**
-     * Add a file descriptor
-     */
-    void add(int fd) {
-        // force the initial update events to 0 as it may be KILLED by a
-        // previous registration.
-        synchronized (updateLock) {
-            assert !registered.get(fd);
-            setUpdateEvents(fd, (byte)0, true);
-        }
-    }
-
-    /**
-     * Remove a file descriptor
-     */
-    void remove(int fd) {
-        synchronized (updateLock) {
-            // kill pending and future update for this file descriptor
-            setUpdateEvents(fd, KILLED, false);
-
-            // remove from epoll
-            if (registered.get(fd)) {
-                epollCtl(epfd, EPOLL_CTL_DEL, fd, 0);
-                registered.clear(fd);
-            }
-        }
-    }
-
-    /**
-     * Close epoll file descriptor and free poll array
-     */
-    void close() throws IOException {
-        FileDispatcherImpl.closeIntFD(epfd);
-        pollArray.free();
-    }
-
-    int poll(long timeout) throws IOException {
-        updateRegistrations();
-        return epollWait(pollArrayAddress, NUM_EPOLLEVENTS, timeout, epfd);
-    }
-
-    /**
-     * Update the pending registrations.
-     */
-    private void updateRegistrations() {
-        synchronized (updateLock) {
-            int j = 0;
-            while (j < updateCount) {
-                int fd = updateDescriptors[j];
-                short events = getUpdateEvents(fd);
-                boolean isRegistered = registered.get(fd);
-                int opcode = 0;
-
-                if (events != KILLED) {
-                    if (isRegistered) {
-                        opcode = (events != 0) ? EPOLL_CTL_MOD : EPOLL_CTL_DEL;
-                    } else {
-                        opcode = (events != 0) ? EPOLL_CTL_ADD : 0;
-                    }
-                    if (opcode != 0) {
-                        epollCtl(epfd, opcode, fd, events);
-                        if (opcode == EPOLL_CTL_ADD) {
-                            registered.set(fd);
-                        } else if (opcode == EPOLL_CTL_DEL) {
-                            registered.clear(fd);
-                        }
-                    }
-                }
-                j++;
-            }
-            updateCount = 0;
-        }
-    }
-
-    public void interrupt() {
-        interrupt(outgoingInterruptFD);
-    }
-
-    static {
-        IOUtil.load();
-        init();
-    }
-
-    private native int epollCreate();
-    private native void epollCtl(int epfd, int opcode, int fd, int events);
-    private native int epollWait(long pollAddress, int numfds, long timeout,
-                                 int epfd) throws IOException;
-    private static native int sizeofEPollEvent();
-    private static native int offsetofData();
-    private static native void interrupt(int fd);
-    private static native void init();
-}
--- a/src/java.base/linux/classes/sun/nio/ch/EPollPort.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/linux/classes/sun/nio/ch/EPollPort.java	Fri Mar 23 11:14:43 2018 -0700
@@ -30,7 +30,13 @@
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
-import static sun.nio.ch.EPoll.*;
+
+import static sun.nio.ch.EPoll.EPOLLIN;
+import static sun.nio.ch.EPoll.EPOLLONESHOT;
+import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
+import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
+import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
+
 
 /**
  * AsynchronousChannelGroup implementation based on the Linux epoll facility.
@@ -48,6 +54,9 @@
     // epoll file descriptor
     private final int epfd;
 
+    // address of the poll array passed to epoll_wait
+    private final long address;
+
     // true if epoll closed
     private boolean closed;
 
@@ -57,9 +66,6 @@
     // number of wakeups pending
     private final AtomicInteger wakeupCount = new AtomicInteger();
 
-    // address of the poll array passed to epoll_wait
-    private final long address;
-
     // encapsulates an event for a channel
     static class Event {
         final PollableChannel channel;
@@ -85,23 +91,21 @@
     {
         super(provider, pool);
 
-        // open epoll
-        this.epfd = epollCreate();
+        this.epfd = EPoll.create();
+        this.address = EPoll.allocatePollArray(MAX_EPOLL_EVENTS);
 
         // create socket pair for wakeup mechanism
-        int[] sv = new int[2];
         try {
-            socketpair(sv);
-            // register one end with epoll
-            epollCtl(epfd, EPOLL_CTL_ADD, sv[0], EPOLLIN);
-        } catch (IOException x) {
-            close0(epfd);
-            throw x;
+            long fds = IOUtil.makePipe(true);
+            this.sp = new int[]{(int) (fds >>> 32), (int) fds};
+        } catch (IOException ioe) {
+            EPoll.freePollArray(address);
+            FileDispatcherImpl.closeIntFD(epfd);
+            throw ioe;
         }
-        this.sp = sv;
 
-        // allocate the poll array
-        this.address = allocatePollArray(MAX_EPOLL_EVENTS);
+        // register one end with epoll
+        EPoll.ctl(epfd, EPOLL_CTL_ADD, sp[0], EPOLLIN);
 
         // create the queue and offer the special event to ensure that the first
         // threads polls
@@ -123,17 +127,17 @@
                 return;
             closed = true;
         }
-        freePollArray(address);
-        close0(sp[0]);
-        close0(sp[1]);
-        close0(epfd);
+        try { FileDispatcherImpl.closeIntFD(epfd); } catch (IOException ioe) { }
+        try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
+        try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
+        EPoll.freePollArray(address);
     }
 
     private void wakeup() {
         if (wakeupCount.incrementAndGet() == 1) {
             // write byte to socketpair to force wakeup
             try {
-                interrupt(sp[1]);
+                IOUtil.write1(sp[1], (byte)0);
             } catch (IOException x) {
                 throw new AssertionError(x);
             }
@@ -171,9 +175,9 @@
     @Override
     void startPoll(int fd, int events) {
         // update events (or add to epoll on first usage)
-        int err = epollCtl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
+        int err = EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, (events | EPOLLONESHOT));
         if (err == ENOENT)
-            err = epollCtl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
+            err = EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, (events | EPOLLONESHOT));
         if (err != 0)
             throw new AssertionError();     // should not happen
     }
@@ -191,7 +195,11 @@
         private Event poll() throws IOException {
             try {
                 for (;;) {
-                    int n = epollWait(epfd, address, MAX_EPOLL_EVENTS);
+                    int n;
+                    do {
+                        n = EPoll.wait(epfd, address, MAX_EPOLL_EVENTS, -1);
+                    } while (n == IOStatus.INTERRUPTED);
+
                     /*
                      * 'n' events have been read. Here we map them to their
                      * corresponding channel in batch and queue n-1 so that
@@ -201,14 +209,14 @@
                     fdToChannelLock.readLock().lock();
                     try {
                         while (n-- > 0) {
-                            long eventAddress = getEvent(address, n);
-                            int fd = getDescriptor(eventAddress);
+                            long eventAddress = EPoll.getEvent(address, n);
+                            int fd = EPoll.getDescriptor(eventAddress);
 
                             // wakeup
                             if (fd == sp[0]) {
                                 if (wakeupCount.decrementAndGet() == 0) {
                                     // no more wakeups so drain pipe
-                                    drain1(sp[0]);
+                                    IOUtil.drain(sp[0]);
                                 }
 
                                 // queue special event if there are more events
@@ -222,7 +230,7 @@
 
                             PollableChannel channel = fdToChannel.get(fd);
                             if (channel != null) {
-                                int events = getEvents(eventAddress);
+                                int events = EPoll.getEvents(eventAddress);
                                 Event ev = new Event(channel, events);
 
                                 // n-1 events are queued; This thread handles
@@ -306,18 +314,4 @@
             }
         }
     }
-
-    // -- Native methods --
-
-    private static native void socketpair(int[] sv) throws IOException;
-
-    private static native void interrupt(int fd) throws IOException;
-
-    private static native void drain1(int fd) throws IOException;
-
-    private static native void close0(int fd);
-
-    static {
-        IOUtil.load();
-    }
 }
--- a/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -26,33 +26,59 @@
 package sun.nio.ch;
 
 import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
-import java.util.*;
+import java.nio.channels.ClosedSelectorException;
+import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.Selector;
+import java.nio.channels.spi.SelectorProvider;
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+
+import static sun.nio.ch.EPoll.EPOLLIN;
+import static sun.nio.ch.EPoll.EPOLL_CTL_ADD;
+import static sun.nio.ch.EPoll.EPOLL_CTL_DEL;
+import static sun.nio.ch.EPoll.EPOLL_CTL_MOD;
+
 
 /**
- * An implementation of Selector for Linux 2.6+ kernels that uses
- * the epoll event notification facility.
+ * Linux epoll based Selector implementation
  */
-class EPollSelectorImpl
-    extends SelectorImpl
-{
-    // File descriptors used for interrupt
+
+class EPollSelectorImpl extends SelectorImpl {
+
+    // maximum number of events to poll in one call to epoll_wait
+    private static final int NUM_EPOLLEVENTS = Math.min(IOUtil.fdLimit(), 1024);
+
+    // epoll file descriptor
+    private final int epfd;
+
+    // address of poll array when polling with epoll_wait
+    private final long pollArrayAddress;
+
+    // file descriptors used for interrupt
     private final int fd0;
     private final int fd1;
 
-    // The poll object
-    private final EPollArrayWrapper pollWrapper;
+    // maps file descriptor to selection key, synchronize on selector
+    private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
 
-    // Maps from file descriptors to keys
-    private final Map<Integer, SelectionKeyImpl> fdToKey;
+    // file descriptors registered with epoll, synchronize on selector
+    private final BitSet registered = new BitSet();
 
-    // True if this Selector has been closed
-    private volatile boolean closed;
+    // pending new registrations/updates, queued by implRegister and putEventOps
+    private final Object updateLock = new Object();
+    private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
+    private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
+    private final Deque<Integer> updateOps = new ArrayDeque<>();
 
-    // Lock for interrupt triggering and clearing
+    // interrupt triggering and clearing
     private final Object interruptLock = new Object();
-    private boolean interruptTriggered = false;
+    private boolean interruptTriggered;
 
     /**
      * Package private constructor called by factory method in
@@ -60,40 +86,57 @@
      */
     EPollSelectorImpl(SelectorProvider sp) throws IOException {
         super(sp);
-        long pipeFds = IOUtil.makePipe(false);
-        fd0 = (int) (pipeFds >>> 32);
-        fd1 = (int) pipeFds;
+
+        this.epfd = EPoll.create();
+        this.pollArrayAddress = EPoll.allocatePollArray(NUM_EPOLLEVENTS);
+
         try {
-            pollWrapper = new EPollArrayWrapper(fd0, fd1);
-            fdToKey = new HashMap<>();
-        } catch (Throwable t) {
-            try {
-                FileDispatcherImpl.closeIntFD(fd0);
-            } catch (IOException ioe0) {
-                t.addSuppressed(ioe0);
-            }
-            try {
-                FileDispatcherImpl.closeIntFD(fd1);
-            } catch (IOException ioe1) {
-                t.addSuppressed(ioe1);
-            }
-            throw t;
+            long fds = IOUtil.makePipe(false);
+            this.fd0 = (int) (fds >>> 32);
+            this.fd1 = (int) fds;
+        } catch (IOException ioe) {
+            EPoll.freePollArray(pollArrayAddress);
+            FileDispatcherImpl.closeIntFD(epfd);
+            throw ioe;
         }
+
+        // register one end of the socket pair for wakeups
+        EPoll.ctl(epfd, EPOLL_CTL_ADD, fd0, EPOLLIN);
     }
 
     private void ensureOpen() {
-        if (closed)
+        if (!isOpen())
             throw new ClosedSelectorException();
     }
 
     @Override
     protected int doSelect(long timeout) throws IOException {
-        ensureOpen();
+        assert Thread.holdsLock(this);
+
         int numEntries;
+        processUpdateQueue();
         processDeregisterQueue();
         try {
             begin();
-            numEntries = pollWrapper.poll(timeout);
+
+            // epoll_wait timeout is int
+            int to = (int) Math.min(timeout, Integer.MAX_VALUE);
+            boolean timedPoll = (to > 0);
+            do {
+                long startTime = timedPoll ? System.nanoTime() : 0;
+                numEntries = EPoll.wait(epfd, pollArrayAddress, NUM_EPOLLEVENTS, to);
+                if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
+                    // timed poll interrupted so need to adjust timeout
+                    long adjust = System.nanoTime() - startTime;
+                    to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
+                    if (to <= 0) {
+                        // timeout expired so no retry
+                        numEntries = 0;
+                    }
+                }
+            } while (numEntries == IOStatus.INTERRUPTED);
+            assert IOStatus.check(numEntries);
+
         } finally {
             end();
         }
@@ -102,20 +145,69 @@
     }
 
     /**
+     * Process new registrations and changes to the interest ops.
+     */
+    private void processUpdateQueue() {
+        assert Thread.holdsLock(this);
+
+        synchronized (updateLock) {
+            SelectionKeyImpl ski;
+
+            // new registrations
+            while ((ski = newKeys.pollFirst()) != null) {
+                if (ski.isValid()) {
+                    SelChImpl ch = ski.channel;
+                    int fd = ch.getFDVal();
+                    SelectionKeyImpl previous = fdToKey.put(fd, ski);
+                    assert previous == null;
+                    assert registered.get(fd) == false;
+                }
+            }
+
+            // changes to interest ops
+            assert updateKeys.size() == updateOps.size();
+            while ((ski = updateKeys.pollFirst()) != null) {
+                int ops = updateOps.pollFirst();
+                int fd = ski.channel.getFDVal();
+                if (ski.isValid() && fdToKey.containsKey(fd)) {
+                    if (registered.get(fd)) {
+                        if (ops == 0) {
+                            // remove from epoll
+                            EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
+                            registered.clear(fd);
+                        } else {
+                            // modify events
+                            EPoll.ctl(epfd, EPOLL_CTL_MOD, fd, ops);
+                        }
+                    } else if (ops != 0) {
+                        // add to epoll
+                        EPoll.ctl(epfd, EPOLL_CTL_ADD, fd, ops);
+                        registered.set(fd);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
      * Update the keys whose fd's have been selected by the epoll.
      * Add the ready keys to the ready queue.
      */
     private int updateSelectedKeys(int numEntries) throws IOException {
+        assert Thread.holdsLock(this);
+        assert Thread.holdsLock(nioSelectedKeys());
+
         boolean interrupted = false;
         int numKeysUpdated = 0;
         for (int i=0; i<numEntries; i++) {
-            int nextFD = pollWrapper.getDescriptor(i);
-            if (nextFD == fd0) {
+            long event = EPoll.getEvent(pollArrayAddress, i);
+            int fd = EPoll.getDescriptor(event);
+            if (fd == fd0) {
                 interrupted = true;
             } else {
-                SelectionKeyImpl ski = fdToKey.get(Integer.valueOf(nextFD));
+                SelectionKeyImpl ski = fdToKey.get(fd);
                 if (ski != null) {
-                    int rOps = pollWrapper.getEventOps(i);
+                    int rOps = EPoll.getEvents(event);
                     if (selectedKeys.contains(ski)) {
                         if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
                             numKeysUpdated++;
@@ -140,16 +232,17 @@
 
     @Override
     protected void implClose() throws IOException {
-        if (closed)
-            return;
-        closed = true;
+        assert Thread.holdsLock(this);
+        assert Thread.holdsLock(nioKeys());
 
         // prevent further wakeup
         synchronized (interruptLock) {
             interruptTriggered = true;
         }
 
-        pollWrapper.close();
+        FileDispatcherImpl.closeIntFD(epfd);
+        EPoll.freePollArray(pollArrayAddress);
+
         FileDispatcherImpl.closeIntFD(fd0);
         FileDispatcherImpl.closeIntFD(fd1);
 
@@ -167,42 +260,57 @@
 
     @Override
     protected void implRegister(SelectionKeyImpl ski) {
+        assert Thread.holdsLock(nioKeys());
         ensureOpen();
-        SelChImpl ch = ski.channel;
-        int fd = Integer.valueOf(ch.getFDVal());
-        fdToKey.put(fd, ski);
-        pollWrapper.add(fd);
+        synchronized (updateLock) {
+            newKeys.addLast(ski);
+        }
         keys.add(ski);
     }
 
     @Override
     protected void implDereg(SelectionKeyImpl ski) throws IOException {
-        assert (ski.getIndex() >= 0);
-        SelChImpl ch = ski.channel;
-        int fd = ch.getFDVal();
-        fdToKey.remove(Integer.valueOf(fd));
-        pollWrapper.remove(fd);
-        ski.setIndex(-1);
+        assert !ski.isValid();
+        assert Thread.holdsLock(this);
+        assert Thread.holdsLock(nioKeys());
+        assert Thread.holdsLock(nioSelectedKeys());
+
+        int fd = ski.channel.getFDVal();
+        fdToKey.remove(fd);
+        if (registered.get(fd)) {
+            EPoll.ctl(epfd, EPOLL_CTL_DEL, fd, 0);
+            registered.clear(fd);
+        }
+
+        selectedKeys.remove(ski);
         keys.remove(ski);
-        selectedKeys.remove(ski);
+
+        // remove from channel's key set
         deregister(ski);
+
         SelectableChannel selch = ski.channel();
         if (!selch.isOpen() && !selch.isRegistered())
-            ((SelChImpl)selch).kill();
+            ((SelChImpl) selch).kill();
     }
 
     @Override
     public void putEventOps(SelectionKeyImpl ski, int ops) {
         ensureOpen();
-        SelChImpl ch = ski.channel;
-        pollWrapper.setInterest(ch.getFDVal(), ops);
+        synchronized (updateLock) {
+            updateOps.addLast(ops);   // ops first in case adding the key fails
+            updateKeys.addLast(ski);
+        }
     }
 
     @Override
     public Selector wakeup() {
         synchronized (interruptLock) {
             if (!interruptTriggered) {
-                pollWrapper.interrupt();
+                try {
+                    IOUtil.write1(fd1, (byte)0);
+                } catch (IOException ioe) {
+                    throw new InternalError(ioe);
+                }
                 interruptTriggered = true;
             }
         }
--- a/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/linux/classes/sun/nio/fs/LinuxFileSystemProvider.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, 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
@@ -103,8 +103,8 @@
     @Override
     FileTypeDetector getFileTypeDetector() {
         String userHome = GetPropertyAction.privilegedGetProperty("user.home");
-        Path userMimeTypes = Paths.get(userHome, ".mime.types");
-        Path etcMimeTypes = Paths.get("/etc/mime.types");
+        Path userMimeTypes = Path.of(userHome, ".mime.types");
+        Path etcMimeTypes = Path.of("/etc/mime.types");
 
         return chain(new MimeTypesFileTypeDetector(userMimeTypes),
                      new MimeTypesFileTypeDetector(etcMimeTypes));
--- a/src/java.base/linux/native/libnio/ch/EPoll.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/linux/native/libnio/ch/EPoll.c	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, 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
@@ -23,53 +23,51 @@
  * questions.
  */
 
+ #include <dlfcn.h>
+ #include <unistd.h>
+ #include <sys/types.h>
+ #include <sys/epoll.h>
+
 #include "jni.h"
 #include "jni_util.h"
 #include "jvm.h"
 #include "jlong.h"
+#include "nio.h"
 #include "nio_util.h"
 
 #include "sun_nio_ch_EPoll.h"
 
-#include <dlfcn.h>
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/epoll.h>
-
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass this)
+Java_sun_nio_ch_EPoll_eventSize(JNIEnv* env, jclass clazz)
 {
     return sizeof(struct epoll_event);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_EPoll_eventsOffset(JNIEnv* env, jclass clazz)
 {
     return offsetof(struct epoll_event, events);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_EPoll_dataOffset(JNIEnv* env, jclass clazz)
 {
     return offsetof(struct epoll_event, data);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_epollCreate(JNIEnv *env, jclass c) {
-    /*
-     * epoll_create expects a size as a hint to the kernel about how to
-     * dimension internal structures. We can't predict the size in advance.
-     */
+Java_sun_nio_ch_EPoll_create(JNIEnv *env, jclass clazz) {
+    /* size hint not used in modern kernels */
     int epfd = epoll_create(256);
     if (epfd < 0) {
-       JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
+        JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
     }
     return epfd;
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd,
-                                   jint opcode, jint fd, jint events)
+Java_sun_nio_ch_EPoll_ctl(JNIEnv *env, jclass clazz, jint epfd,
+                          jint opcode, jint fd, jint events)
 {
     struct epoll_event event;
     int res;
@@ -77,21 +75,23 @@
     event.events = events;
     event.data.fd = fd;
 
-    RESTARTABLE(epoll_ctl(epfd, (int)opcode, (int)fd, &event), res);
-
+    res = epoll_ctl(epfd, (int)opcode, (int)fd, &event);
     return (res == 0) ? 0 : errno;
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPoll_epollWait(JNIEnv *env, jclass c,
-                                    jint epfd, jlong address, jint numfds)
+Java_sun_nio_ch_EPoll_wait(JNIEnv *env, jclass clazz, jint epfd,
+                           jlong address, jint numfds, jint timeout)
 {
     struct epoll_event *events = jlong_to_ptr(address);
-    int res;
-
-    RESTARTABLE(epoll_wait(epfd, events, numfds, -1), res);
+    int res = epoll_wait(epfd, events, numfds, timeout);
     if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
+            return IOS_THROWN;
+        }
     }
     return res;
 }
--- a/src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-/*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-
-#include "sun_nio_ch_EPollArrayWrapper.h"
-
-#include <unistd.h>
-#include <sys/time.h>
-#include <sys/epoll.h>
-
-#define RESTARTABLE(_cmd, _result) do { \
-  do { \
-    _result = _cmd; \
-  } while((_result == -1) && (errno == EINTR)); \
-} while(0)
-
-
-static int
-iepoll(int epfd, struct epoll_event *events, int numfds, jlong timeout)
-{
-    jlong start, now;
-    int remaining = timeout;
-    struct timeval t;
-    int diff;
-
-    gettimeofday(&t, NULL);
-    start = t.tv_sec * 1000 + t.tv_usec / 1000;
-
-    for (;;) {
-        int res = epoll_wait(epfd, events, numfds, remaining);
-        if (res < 0 && errno == EINTR) {
-            if (remaining >= 0) {
-                gettimeofday(&t, NULL);
-                now = t.tv_sec * 1000 + t.tv_usec / 1000;
-                diff = now - start;
-                remaining -= diff;
-                if (diff < 0 || remaining <= 0) {
-                    return 0;
-                }
-                start = now;
-            }
-        } else {
-            return res;
-        }
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_init(JNIEnv *env, jclass this)
-{
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_epollCreate(JNIEnv *env, jobject this)
-{
-    /*
-     * epoll_create expects a size as a hint to the kernel about how to
-     * dimension internal structures. We can't predict the size in advance.
-     */
-    int epfd = epoll_create(256);
-    if (epfd < 0) {
-       JNU_ThrowIOExceptionWithLastError(env, "epoll_create failed");
-    }
-    return epfd;
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent(JNIEnv* env, jclass this)
-{
-    return sizeof(struct epoll_event);
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_offsetofData(JNIEnv* env, jclass this)
-{
-    return offsetof(struct epoll_event, data);
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_epollCtl(JNIEnv *env, jobject this, jint epfd,
-                                           jint opcode, jint fd, jint events)
-{
-    struct epoll_event event;
-    int res;
-
-    event.events = events;
-    event.data.fd = fd;
-
-    RESTARTABLE(epoll_ctl(epfd, (int)opcode, (int)fd, &event), res);
-
-    /*
-     * A channel may be registered with several Selectors. When each Selector
-     * is polled a EPOLL_CTL_DEL op will be inserted into its pending update
-     * list to remove the file descriptor from epoll. The "last" Selector will
-     * close the file descriptor which automatically unregisters it from each
-     * epoll descriptor. To avoid costly synchronization between Selectors we
-     * allow pending updates to be processed, ignoring errors. The errors are
-     * harmless as the last update for the file descriptor is guaranteed to
-     * be EPOLL_CTL_DEL.
-     */
-    if (res < 0 && errno != EBADF && errno != ENOENT && errno != EPERM) {
-        JNU_ThrowIOExceptionWithLastError(env, "epoll_ctl failed");
-    }
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_epollWait(JNIEnv *env, jobject this,
-                                            jlong address, jint numfds,
-                                            jlong timeout, jint epfd)
-{
-    struct epoll_event *events = jlong_to_ptr(address);
-    int res;
-
-    if (timeout <= 0) {           /* Indefinite or no wait */
-        RESTARTABLE(epoll_wait(epfd, events, numfds, timeout), res);
-    } else {                      /* Bounded wait; bounded restarts */
-        res = iepoll(epfd, events, numfds, timeout);
-    }
-
-    if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
-    }
-    return res;
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd)
-{
-    int fakebuf[1];
-    fakebuf[0] = 1;
-    if (write(fd, fakebuf, 1) < 0) {
-        JNU_ThrowIOExceptionWithLastError(env,"write to interrupt fd failed");
-    }
-}
--- a/src/java.base/linux/native/libnio/ch/EPollPort.c	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include "sun_nio_ch_EPollPort.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
-    int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
-        JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
-    } else {
-        jint res[2];
-        res[0] = (jint)sp[0];
-        res[1] = (jint)sp[1];
-        (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_interrupt(JNIEnv *env, jclass c, jint fd) {
-    int res;
-    int buf[1];
-    buf[0] = 1;
-    RESTARTABLE(write(fd, buf, 1), res);
-    if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "write failed");
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_drain1(JNIEnv *env, jclass cl, jint fd) {
-    int res;
-    char buf[1];
-    RESTARTABLE(read(fd, buf, 1), res);
-    if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_EPollPort_close0(JNIEnv *env, jclass c, jint fd) {
-    int res;
-    RESTARTABLE(close(fd), res);
-}
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueue.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueue.java	Fri Mar 23 11:14:43 2018 -0700
@@ -84,17 +84,17 @@
     }
 
     /**
-     * Returns the file descriptor from a kevent (assuming to be in ident field)
+     * Returns the file descriptor from a kevent (assuming it is in the ident field)
      */
     static int getDescriptor(long address) {
         return unsafe.getInt(address + OFFSET_IDENT);
     }
 
-    static int getFilter(long address) {
+    static short getFilter(long address) {
         return unsafe.getShort(address + OFFSET_FILTER);
     }
 
-    static int getFlags(long address) {
+    static short getFlags(long address) {
         return unsafe.getShort(address + OFFSET_FLAGS);
     }
 
@@ -108,11 +108,11 @@
 
     private static native int flagsOffset();
 
-    static native int kqueue() throws IOException;
+    static native int create() throws IOException;
 
-    static native int keventRegister(int kqpfd, int fd, int filter, int flags);
+    static native int register(int kqfd, int fd, int filter, int flags);
 
-    static native int keventPoll(int kqpfd, long pollAddress, int nevents)
+    static native int poll(int kqfd, long pollAddress, int nevents, long timeout)
         throws IOException;
 
     static {
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,197 +0,0 @@
-/*
- * 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
- * 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.
- */
-
-/*
- * KQueueArrayWrapper.java
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- * Derived from Sun's DevPollArrayWrapper
- */
-
-package sun.nio.ch;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedList;
-import sun.security.action.GetPropertyAction;
-
-/*
- * struct kevent {           // 32-bit    64-bit
- *     uintptr_t ident;      //   4         8
- *     short     filter;     //   2         2
- *     u_short   flags;      //   2         2
- *     u_int     fflags;     //   4         4
- *     intptr_t  data;       //   4         8
- *     void      *udata;     //   4         8
- * }                  // Total:  20        32
- *
- * The implementation works in 32-bit and 64-bit world. We do this by calling a
- * native function that actually sets the sizes and offsets of the fields based
- * on which mode we're in.
- */
-
-class KQueueArrayWrapper {
-    // kevent filters
-    static short EVFILT_READ;
-    static short EVFILT_WRITE;
-
-    // kevent struct
-    // These fields are now set by initStructSizes in the static initializer.
-    static short SIZEOF_KEVENT;
-    static short FD_OFFSET;
-    static short FILTER_OFFSET;
-
-    // kevent array size
-    static final int NUM_KEVENTS = 128;
-
-    // Are we in a 64-bit VM?
-    static boolean is64bit;
-
-    // The kevent array (used for outcoming events only)
-    private final AllocatedNativeObject keventArray;
-    private final long keventArrayAddress;
-
-    // The kqueue fd
-    private final int kq;
-
-    // The fd of the interrupt line going out
-    private final int outgoingInterruptFD;
-
-
-    static {
-        IOUtil.load();
-        initStructSizes();
-        String datamodel =
-                GetPropertyAction.privilegedGetProperty("sun.arch.data.model");
-        is64bit = "64".equals(datamodel);
-    }
-
-    KQueueArrayWrapper(int fd0, int fd1) throws IOException {
-        int allocationSize = SIZEOF_KEVENT * NUM_KEVENTS;
-        keventArray = new AllocatedNativeObject(allocationSize, true);
-        keventArrayAddress = keventArray.address();
-        kq = init();
-        register0(kq, fd0, 1, 0);
-        outgoingInterruptFD = fd1;
-    }
-
-    // Used to update file description registrations
-    private static class Update {
-        SelChImpl channel;
-        int events;
-        Update(SelChImpl channel, int events) {
-            this.channel = channel;
-            this.events = events;
-        }
-    }
-
-    private LinkedList<Update> updateList = new LinkedList<Update>();
-
-    int getReventOps(int index) {
-        int result = 0;
-        int offset = SIZEOF_KEVENT*index + FILTER_OFFSET;
-        short filter = keventArray.getShort(offset);
-
-        // This is all that's necessary based on inspection of usage:
-        //   SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
-        //   ServerSocketChannelImpl, SocketChannelImpl
-        if (filter == EVFILT_READ) {
-            result |= Net.POLLIN;
-        } else if (filter == EVFILT_WRITE) {
-            result |= Net.POLLOUT;
-        }
-
-        return result;
-    }
-
-    int getDescriptor(int index) {
-        int offset = SIZEOF_KEVENT*index + FD_OFFSET;
-        /* The ident field is 8 bytes in 64-bit world, however the API wants us
-         * to return an int. Hence read the 8 bytes but return as an int.
-         */
-        if (is64bit) {
-            long fd = keventArray.getLong(offset);
-            assert fd <= Integer.MAX_VALUE;
-            return (int) fd;
-        } else {
-            return keventArray.getInt(offset);
-        }
-    }
-
-    void setInterest(SelChImpl channel, int events) {
-        synchronized (updateList) {
-            // update existing registration
-            updateList.add(new Update(channel, events));
-        }
-    }
-
-    void release(SelChImpl channel) {
-        synchronized (updateList) {
-            // flush any pending updates
-            for (Iterator<Update> it = updateList.iterator(); it.hasNext();) {
-                if (it.next().channel == channel) {
-                    it.remove();
-                }
-            }
-
-            // remove
-            register0(kq, channel.getFDVal(), 0, 0);
-        }
-    }
-
-    void updateRegistrations() {
-        synchronized (updateList) {
-            Update u;
-            while ((u = updateList.poll()) != null) {
-                SelChImpl ch = u.channel;
-                if (!ch.isOpen())
-                    continue;
-
-                register0(kq, ch.getFDVal(), u.events & Net.POLLIN, u.events & Net.POLLOUT);
-            }
-        }
-    }
-
-    void close() throws IOException {
-        FileDispatcherImpl.closeIntFD(kq);
-        keventArray.free();
-    }
-
-    int poll(long timeout) {
-        updateRegistrations();
-        return kevent0(kq, keventArrayAddress, NUM_KEVENTS, timeout);
-    }
-
-    void interrupt() {
-        interrupt(outgoingInterruptFD);
-    }
-
-    private native int init();
-    private static native void initStructSizes();
-
-    private native void register0(int kq, int fd, int read, int write);
-    private native int kevent0(int kq, long keventAddress, int keventCount,
-                               long timeout);
-    private static native void interrupt(int fd);
-}
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -30,7 +30,11 @@
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
-import static sun.nio.ch.KQueue.*;
+
+import static sun.nio.ch.KQueue.EVFILT_READ;
+import static sun.nio.ch.KQueue.EVFILT_WRITE;
+import static sun.nio.ch.KQueue.EV_ADD;
+import static sun.nio.ch.KQueue.EV_ONESHOT;
 
 /**
  * AsynchronousChannelGroup implementation based on the BSD kqueue facility.
@@ -45,6 +49,9 @@
     // kqueue file descriptor
     private final int kqfd;
 
+    // address of the poll array passed to kqueue_wait
+    private final long address;
+
     // true if kqueue closed
     private boolean closed;
 
@@ -54,9 +61,6 @@
     // number of wakeups pending
     private final AtomicInteger wakeupCount = new AtomicInteger();
 
-    // address of the poll array passed to kqueue_wait
-    private final long address;
-
     // encapsulates an event for a channel
     static class Event {
         final PollableChannel channel;
@@ -82,28 +86,25 @@
     {
         super(provider, pool);
 
-        // open kqueue
-        this.kqfd = kqueue();
+        this.kqfd = KQueue.create();
+        this.address = KQueue.allocatePollArray(MAX_KEVENTS_TO_POLL);
 
         // create socket pair for wakeup mechanism
-        int[] sv = new int[2];
         try {
-            socketpair(sv);
+            long fds = IOUtil.makePipe(true);
+            this.sp = new int[]{(int) (fds >>> 32), (int) fds};
+        } catch (IOException ioe) {
+            KQueue.freePollArray(address);
+            FileDispatcherImpl.closeIntFD(kqfd);
+            throw ioe;
+        }
 
-            // register one end with kqueue
-            keventRegister(kqfd, sv[0], EVFILT_READ, EV_ADD);
-        } catch (IOException x) {
-            close0(kqfd);
-            throw x;
-        }
-        this.sp = sv;
-
-        // allocate the poll array
-        this.address = allocatePollArray(MAX_KEVENTS_TO_POLL);
+        // register one end with kqueue
+        KQueue.register(kqfd, sp[0], EVFILT_READ, EV_ADD);
 
         // create the queue and offer the special event to ensure that the first
         // threads polls
-        this.queue = new ArrayBlockingQueue<Event>(MAX_KEVENTS_TO_POLL);
+        this.queue = new ArrayBlockingQueue<>(MAX_KEVENTS_TO_POLL);
         this.queue.offer(NEED_TO_POLL);
     }
 
@@ -121,17 +122,18 @@
                 return;
             closed = true;
         }
-        freePollArray(address);
-        close0(sp[0]);
-        close0(sp[1]);
-        close0(kqfd);
+
+        try { FileDispatcherImpl.closeIntFD(kqfd); } catch (IOException ioe) { }
+        try { FileDispatcherImpl.closeIntFD(sp[0]); } catch (IOException ioe) { }
+        try { FileDispatcherImpl.closeIntFD(sp[1]); } catch (IOException ioe) { }
+        KQueue.freePollArray(address);
     }
 
     private void wakeup() {
         if (wakeupCount.incrementAndGet() == 1) {
             // write byte to socketpair to force wakeup
             try {
-                interrupt(sp[1]);
+                IOUtil.write1(sp[1], (byte)0);
             } catch (IOException x) {
                 throw new AssertionError(x);
             }
@@ -173,9 +175,9 @@
         int err = 0;
         int flags = (EV_ADD|EV_ONESHOT);
         if ((events & Net.POLLIN) > 0)
-            err = keventRegister(kqfd, fd, EVFILT_READ, flags);
+            err = KQueue.register(kqfd, fd, EVFILT_READ, flags);
         if (err == 0 && (events & Net.POLLOUT) > 0)
-            err = keventRegister(kqfd, fd, EVFILT_WRITE, flags);
+            err = KQueue.register(kqfd, fd, EVFILT_WRITE, flags);
         if (err != 0)
             throw new InternalError("kevent failed: " + err);  // should not happen
     }
@@ -193,7 +195,11 @@
         private Event poll() throws IOException {
             try {
                 for (;;) {
-                    int n = keventPoll(kqfd, address, MAX_KEVENTS_TO_POLL);
+                    int n;
+                    do {
+                        n = KQueue.poll(kqfd, address, MAX_KEVENTS_TO_POLL, -1L);
+                    } while (n == IOStatus.INTERRUPTED);
+
                     /*
                      * 'n' events have been read. Here we map them to their
                      * corresponding channel in batch and queue n-1 so that
@@ -203,14 +209,14 @@
                     fdToChannelLock.readLock().lock();
                     try {
                         while (n-- > 0) {
-                            long keventAddress = getEvent(address, n);
-                            int fd = getDescriptor(keventAddress);
+                            long keventAddress = KQueue.getEvent(address, n);
+                            int fd = KQueue.getDescriptor(keventAddress);
 
                             // wakeup
                             if (fd == sp[0]) {
                                 if (wakeupCount.decrementAndGet() == 0) {
                                     // no more wakeups so drain pipe
-                                    drain1(sp[0]);
+                                    IOUtil.drain(sp[0]);
                                 }
 
                                 // queue special event if there are more events
@@ -224,7 +230,7 @@
 
                             PollableChannel channel = fdToChannel.get(fd);
                             if (channel != null) {
-                                int filter = getFilter(keventAddress);
+                                int filter = KQueue.getFilter(keventAddress);
                                 int events = 0;
                                 if (filter == EVFILT_READ)
                                     events = Net.POLLIN;
@@ -314,18 +320,4 @@
             }
         }
     }
-
-    // -- Native methods --
-
-    private static native void socketpair(int[] sv) throws IOException;
-
-    private static native void interrupt(int fd) throws IOException;
-
-    private static native void drain1(int fd) throws IOException;
-
-    private static native void close0(int fd);
-
-    static {
-        IOUtil.load();
-    }
 }
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -23,11 +23,6 @@
  * questions.
  */
 
-/*
- * KQueueSelectorImpl.java
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- */
-
 package sun.nio.ch;
 
 import java.io.IOException;
@@ -36,85 +31,111 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.Selector;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
-class KQueueSelectorImpl
-    extends SelectorImpl
-{
-    // File descriptors used for interrupt
+import static sun.nio.ch.KQueue.EVFILT_READ;
+import static sun.nio.ch.KQueue.EVFILT_WRITE;
+import static sun.nio.ch.KQueue.EV_ADD;
+import static sun.nio.ch.KQueue.EV_DELETE;
+
+/**
+ * KQueue based Selector implementation for macOS
+ */
+
+class KQueueSelectorImpl extends SelectorImpl {
+
+    // maximum number of events to poll in one call to kqueue
+    private static final int MAX_KEVENTS = 256;
+
+    // kqueue file descriptor
+    private final int kqfd;
+
+    // address of poll array (event list) when polling for pending events
+    private final long pollArrayAddress;
+
+    // file descriptors used for interrupt
     private final int fd0;
     private final int fd1;
 
-    // The kqueue manipulator
-    private final KQueueArrayWrapper kqueueWrapper;
+    // maps file descriptor to selection key, synchronize on selector
+    private final Map<Integer, SelectionKeyImpl> fdToKey = new HashMap<>();
 
-    // Map from a file descriptor to an entry containing the selection key
-    private final HashMap<Integer, MapEntry> fdMap;
+    // file descriptors registered with kqueue, synchronize on selector
+    private final BitSet registeredReadFilter = new BitSet();
+    private final BitSet registeredWriteFilter = new BitSet();
 
-    // True if this Selector has been closed
-    private boolean closed;
+    // pending new registrations/updates, queued by implRegister and putEventOps
+    private final Object updateLock = new Object();
+    private final Deque<SelectionKeyImpl> newKeys = new ArrayDeque<>();
+    private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
+    private final Deque<Integer> updateOps = new ArrayDeque<>();
 
-    // Lock for interrupt triggering and clearing
+    // interrupt triggering and clearing
     private final Object interruptLock = new Object();
     private boolean interruptTriggered;
 
     // used by updateSelectedKeys to handle cases where the same file
     // descriptor is polled by more than one filter
-    private long updateCount;
+    private int pollCount;
 
-    // Used to map file descriptors to a selection key and "update count"
-    // (see updateSelectedKeys for usage).
-    private static class MapEntry {
-        SelectionKeyImpl ski;
-        long updateCount;
-        MapEntry(SelectionKeyImpl ski) {
-            this.ski = ski;
-        }
-    }
-
-    /**
-     * Package private constructor called by factory method in
-     * the abstract superclass Selector.
-     */
     KQueueSelectorImpl(SelectorProvider sp) throws IOException {
         super(sp);
-        long fds = IOUtil.makePipe(false);
-        fd0 = (int)(fds >>> 32);
-        fd1 = (int)fds;
+
+        this.kqfd = KQueue.create();
+        this.pollArrayAddress = KQueue.allocatePollArray(MAX_KEVENTS);
+
         try {
-            kqueueWrapper = new KQueueArrayWrapper(fd0, fd1);
-            fdMap = new HashMap<>();
-        } catch (Throwable t) {
-            try {
-                FileDispatcherImpl.closeIntFD(fd0);
-            } catch (IOException ioe0) {
-                t.addSuppressed(ioe0);
-            }
-            try {
-                FileDispatcherImpl.closeIntFD(fd1);
-            } catch (IOException ioe1) {
-                t.addSuppressed(ioe1);
-            }
-            throw t;
+            long fds = IOUtil.makePipe(false);
+            this.fd0 = (int) (fds >>> 32);
+            this.fd1 = (int) fds;
+        } catch (IOException ioe) {
+            KQueue.freePollArray(pollArrayAddress);
+            FileDispatcherImpl.closeIntFD(kqfd);
+            throw ioe;
         }
+
+        // register one end of the socket pair for wakeups
+        KQueue.register(kqfd, fd0, EVFILT_READ, EV_ADD);
     }
 
     private void ensureOpen() {
-        if (closed)
+        if (!isOpen())
             throw new ClosedSelectorException();
     }
 
     @Override
-    protected int doSelect(long timeout)
-        throws IOException
-    {
-        ensureOpen();
+    protected int doSelect(long timeout) throws IOException {
+        assert Thread.holdsLock(this);
+
         int numEntries;
+        processUpdateQueue();
         processDeregisterQueue();
         try {
             begin();
-            numEntries = kqueueWrapper.poll(timeout);
+
+            long to = Math.min(timeout, Integer.MAX_VALUE);  // max kqueue timeout
+            boolean timedPoll = (to > 0);
+            do {
+                long startTime = timedPoll ? System.nanoTime() : 0;
+                numEntries = KQueue.poll(kqfd, pollArrayAddress, MAX_KEVENTS, to);
+                if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
+                    // timed poll interrupted so need to adjust timeout
+                    long adjust = System.nanoTime() - startTime;
+                    to -= TimeUnit.MILLISECONDS.convert(adjust, TimeUnit.NANOSECONDS);
+                    if (to <= 0) {
+                        // timeout expired so no retry
+                        numEntries = 0;
+                    }
+                }
+            } while (numEntries == IOStatus.INTERRUPTED);
+            assert IOStatus.check(numEntries);
+
         } finally {
             end();
         }
@@ -123,39 +144,100 @@
     }
 
     /**
+     * Process new registrations and changes to the interest ops.
+     */
+    private void processUpdateQueue() {
+        assert Thread.holdsLock(this);
+
+        synchronized (updateLock) {
+            SelectionKeyImpl ski;
+
+            // new registrations
+            while ((ski = newKeys.pollFirst()) != null) {
+                if (ski.isValid()) {
+                    SelChImpl ch = ski.channel;
+                    int fd = ch.getFDVal();
+                    SelectionKeyImpl previous = fdToKey.put(fd, ski);
+                    assert previous == null;
+                    assert registeredReadFilter.get(fd) == false;
+                    assert registeredWriteFilter.get(fd) == false;
+                }
+            }
+
+            // changes to interest ops
+            assert updateKeys.size() == updateOps.size();
+            while ((ski = updateKeys.pollFirst()) != null) {
+                int ops = updateOps.pollFirst();
+                int fd = ski.channel.getFDVal();
+                if (ski.isValid() && fdToKey.containsKey(fd)) {
+                    // add or delete interest in read events
+                    if (registeredReadFilter.get(fd)) {
+                        if ((ops & Net.POLLIN) == 0) {
+                            KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
+                            registeredReadFilter.clear(fd);
+                        }
+                    } else if ((ops & Net.POLLIN) != 0) {
+                        KQueue.register(kqfd, fd, EVFILT_READ, EV_ADD);
+                        registeredReadFilter.set(fd);
+                    }
+
+                    // add or delete interest in write events
+                    if (registeredWriteFilter.get(fd)) {
+                        if ((ops & Net.POLLOUT) == 0) {
+                            KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
+                            registeredWriteFilter.clear(fd);
+                        }
+                    } else if ((ops & Net.POLLOUT) != 0) {
+                        KQueue.register(kqfd, fd, EVFILT_WRITE, EV_ADD);
+                        registeredWriteFilter.set(fd);
+                    }
+                }
+            }
+        }
+    }
+
+    /**
      * Update the keys whose fd's have been selected by kqueue.
      * Add the ready keys to the selected key set.
      * If the interrupt fd has been selected, drain it and clear the interrupt.
      */
-    private int updateSelectedKeys(int numEntries)
-        throws IOException
-    {
+    private int updateSelectedKeys(int numEntries) throws IOException {
+        assert Thread.holdsLock(this);
+        assert Thread.holdsLock(nioSelectedKeys());
+
         int numKeysUpdated = 0;
         boolean interrupted = false;
 
         // A file descriptor may be registered with kqueue with more than one
-        // filter and so there may be more than one event for a fd. The update
-        // count in the MapEntry tracks when the fd was last updated and this
-        // ensures that the ready ops are updated rather than replaced by a
-        // second or subsequent event.
-        updateCount++;
+        // filter and so there may be more than one event for a fd. The poll
+        // count is incremented here and compared against the SelectionKey's
+        // "lastPolled" field. This ensures that the ready ops is updated rather
+        // than replaced when a file descriptor is polled by both the read and
+        // write filter.
+        pollCount++;
 
         for (int i = 0; i < numEntries; i++) {
-            int nextFD = kqueueWrapper.getDescriptor(i);
-            if (nextFD == fd0) {
+            long kevent = KQueue.getEvent(pollArrayAddress, i);
+            int fd = KQueue.getDescriptor(kevent);
+            if (fd == fd0) {
                 interrupted = true;
             } else {
-                MapEntry me = fdMap.get(Integer.valueOf(nextFD));
-                if (me != null) {
-                    int rOps = kqueueWrapper.getReventOps(i);
-                    SelectionKeyImpl ski = me.ski;
+                SelectionKeyImpl ski = fdToKey.get(fd);
+                if (ski != null) {
+                    int rOps = 0;
+                    short filter = KQueue.getFilter(kevent);
+                    if (filter == EVFILT_READ) {
+                        rOps |= Net.POLLIN;
+                    } else if (filter == EVFILT_WRITE) {
+                        rOps |= Net.POLLOUT;
+                    }
+
                     if (selectedKeys.contains(ski)) {
-                        // first time this file descriptor has been encountered on this
-                        // update?
-                        if (me.updateCount != updateCount) {
+                        // file descriptor may be polled more than once per poll
+                        if (ski.lastPolled != pollCount) {
                             if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
                                 numKeysUpdated++;
-                                me.updateCount = updateCount;
+                                ski.lastPolled = pollCount;
                             }
                         } else {
                             // ready ops have already been set on this update
@@ -166,7 +248,7 @@
                         if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
                             selectedKeys.add(ski);
                             numKeysUpdated++;
-                            me.updateCount = updateCount;
+                            ski.lastPolled = pollCount;
                         }
                     }
                 }
@@ -181,63 +263,90 @@
 
     @Override
     protected void implClose() throws IOException {
-        if (!closed) {
-            closed = true;
+        assert !isOpen();
+        assert Thread.holdsLock(this);
+        assert Thread.holdsLock(nioKeys());
 
-            // prevent further wakeup
-            synchronized (interruptLock) {
-                interruptTriggered = true;
-            }
+        // prevent further wakeup
+        synchronized (interruptLock) {
+            interruptTriggered = true;
+        }
 
-            kqueueWrapper.close();
-            FileDispatcherImpl.closeIntFD(fd0);
-            FileDispatcherImpl.closeIntFD(fd1);
+        FileDispatcherImpl.closeIntFD(kqfd);
+        KQueue.freePollArray(pollArrayAddress);
 
-            // Deregister channels
-            Iterator<SelectionKey> i = keys.iterator();
-            while (i.hasNext()) {
-                SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
-                deregister(ski);
-                SelectableChannel selch = ski.channel();
-                if (!selch.isOpen() && !selch.isRegistered())
-                    ((SelChImpl)selch).kill();
-                i.remove();
-            }
+        FileDispatcherImpl.closeIntFD(fd0);
+        FileDispatcherImpl.closeIntFD(fd1);
+
+        // Deregister channels
+        Iterator<SelectionKey> i = keys.iterator();
+        while (i.hasNext()) {
+            SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
+            deregister(ski);
+            SelectableChannel selch = ski.channel();
+            if (!selch.isOpen() && !selch.isRegistered())
+                ((SelChImpl)selch).kill();
+            i.remove();
         }
     }
 
     @Override
     protected void implRegister(SelectionKeyImpl ski) {
+        assert Thread.holdsLock(nioKeys());
         ensureOpen();
-        int fd = IOUtil.fdVal(ski.channel.getFD());
-        fdMap.put(Integer.valueOf(fd), new MapEntry(ski));
+        synchronized (updateLock) {
+            newKeys.addLast(ski);
+        }
         keys.add(ski);
     }
 
     @Override
     protected void implDereg(SelectionKeyImpl ski) throws IOException {
+        assert !ski.isValid();
+        assert Thread.holdsLock(this);
+        assert Thread.holdsLock(nioKeys());
+        assert Thread.holdsLock(nioSelectedKeys());
+
         int fd = ski.channel.getFDVal();
-        fdMap.remove(Integer.valueOf(fd));
-        kqueueWrapper.release(ski.channel);
+        fdToKey.remove(fd);
+        if (registeredReadFilter.get(fd)) {
+            KQueue.register(kqfd, fd, EVFILT_READ, EV_DELETE);
+            registeredReadFilter.clear(fd);
+        }
+        if (registeredWriteFilter.get(fd)) {
+            KQueue.register(kqfd, fd, EVFILT_WRITE, EV_DELETE);
+            registeredWriteFilter.clear(fd);
+        }
+
+        selectedKeys.remove(ski);
         keys.remove(ski);
-        selectedKeys.remove(ski);
+
+        // remove from channel's key set
         deregister(ski);
+
         SelectableChannel selch = ski.channel();
         if (!selch.isOpen() && !selch.isRegistered())
-            ((SelChImpl)selch).kill();
+            ((SelChImpl) selch).kill();
     }
 
     @Override
     public void putEventOps(SelectionKeyImpl ski, int ops) {
         ensureOpen();
-        kqueueWrapper.setInterest(ski.channel, ops);
+        synchronized (updateLock) {
+            updateOps.addLast(ops);   // ops first in case adding the key fails
+            updateKeys.addLast(ski);
+        }
     }
 
     @Override
     public Selector wakeup() {
         synchronized (interruptLock) {
             if (!interruptTriggered) {
-                kqueueWrapper.interrupt();
+                try {
+                    IOUtil.write1(fd1, (byte)0);
+                } catch (IOException ioe) {
+                    throw new InternalError(ioe);
+                }
                 interruptTriggered = true;
             }
         }
--- a/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java	Fri Mar 23 11:14:43 2018 -0700
@@ -23,17 +23,10 @@
  * questions.
  */
 
-/*
- * KQueueSelectorProvider.java
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- * Derived from Sun's DevPollSelectorProvider
- */
-
 package sun.nio.ch;
 
 import java.io.IOException;
-import java.nio.channels.*;
-import java.nio.channels.spi.*;
+import java.nio.channels.spi.AbstractSelector;
 
 public class KQueueSelectorProvider
     extends SelectorProviderImpl
--- a/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/macosx/classes/sun/nio/fs/MacOSXFileSystemProvider.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2015, 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
@@ -26,7 +26,6 @@
 package sun.nio.fs;
 
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.spi.FileTypeDetector;
 import sun.security.action.GetPropertyAction;
 
@@ -46,7 +45,7 @@
 
     @Override
     FileTypeDetector getFileTypeDetector() {
-        Path userMimeTypes = Paths.get(GetPropertyAction
+        Path userMimeTypes = Path.of(GetPropertyAction
                 .privilegedGetProperty("user.home"), ".mime.types");
 
         return chain(new MimeTypesFileTypeDetector(userMimeTypes),
--- a/src/java.base/macosx/native/libnio/ch/KQueue.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/macosx/native/libnio/ch/KQueue.c	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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,76 +23,91 @@
  * questions.
  */
 
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include "sun_nio_ch_KQueue.h"
-
 #include <strings.h>
 #include <sys/types.h>
 #include <sys/event.h>
 #include <sys/time.h>
 
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "nio.h"
+#include "nio_util.h"
+
+#include "sun_nio_ch_KQueue.h"
+
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_keventSize(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_keventSize(JNIEnv* env, jclass clazz)
 {
     return sizeof(struct kevent);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_identOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_identOffset(JNIEnv* env, jclass clazz)
 {
     return offsetof(struct kevent, ident);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_filterOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_filterOffset(JNIEnv* env, jclass clazz)
 {
     return offsetof(struct kevent, filter);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_flagsOffset(JNIEnv* env, jclass this)
+Java_sun_nio_ch_KQueue_flagsOffset(JNIEnv* env, jclass clazz)
 {
     return offsetof(struct kevent, flags);
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_kqueue(JNIEnv *env, jclass c) {
+Java_sun_nio_ch_KQueue_create(JNIEnv *env, jclass clazz) {
     int kqfd = kqueue();
     if (kqfd < 0) {
         JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
+        return IOS_THROWN;
     }
     return kqfd;
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_keventRegister(JNIEnv *env, jclass c, jint kqfd,
-                                      jint fd, jint filter, jint flags)
+Java_sun_nio_ch_KQueue_register(JNIEnv *env, jclass clazz, jint kqfd,
+                                jint fd, jint filter, jint flags)
 
 {
     struct kevent changes[1];
-    struct timespec timeout = {0, 0};
     int res;
 
     EV_SET(&changes[0], fd, filter, flags, 0, 0, 0);
-    RESTARTABLE(kevent(kqfd, &changes[0], 1, NULL, 0, &timeout), res);
+    RESTARTABLE(kevent(kqfd, &changes[0], 1, NULL, 0, NULL), res);
     return (res == -1) ? errno : 0;
 }
 
 JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueue_keventPoll(JNIEnv *env, jclass c,
-                                  jint kqfd, jlong address, jint nevents)
+Java_sun_nio_ch_KQueue_poll(JNIEnv *env, jclass clazz, jint kqfd, jlong address,
+                            jint nevents, jlong timeout)
 {
     struct kevent *events = jlong_to_ptr(address);
     int res;
+    struct timespec ts;
+    struct timespec *tsp;
 
-    RESTARTABLE(kevent(kqfd, NULL, 0, events, nevents, NULL), res);
+    if (timeout >= 0) {
+        ts.tv_sec = timeout / 1000;
+        ts.tv_nsec = (timeout % 1000) * 1000000;
+        tsp = &ts;
+    } else {
+        tsp = NULL;
+    }
+
+    res = kevent(kqfd, NULL, 0, events, nevents, tsp);
     if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "kqueue failed");
+            return IOS_THROWN;
+        }
     }
     return res;
 }
--- a/src/java.base/macosx/native/libnio/ch/KQueueArrayWrapper.c	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,175 +0,0 @@
-/*
- * 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
- * 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.
- */
-
-/*
- * KQueueArrayWrapper.c
- * Implementation of Selector using FreeBSD / Mac OS X kqueues
- * Derived from Sun's DevPollArrayWrapper
- */
-
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include <sys/types.h>
-#include <sys/event.h>
-#include <sys/time.h>
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_initStructSizes(JNIEnv *env, jclass clazz)
-{
-#define CHECK_EXCEPTION() { \
-    if ((*env)->ExceptionCheck(env)) { \
-        goto exceptionOccurred; \
-    } \
-}
-
-#define CHECK_ERROR_AND_EXCEPTION(_field) { \
-    if (_field == NULL) { \
-        goto badField; \
-    } \
-    CHECK_EXCEPTION(); \
-}
-
-
-    jfieldID field;
-
-    field = (*env)->GetStaticFieldID(env, clazz, "EVFILT_READ", "S");
-    CHECK_ERROR_AND_EXCEPTION(field);
-    (*env)->SetStaticShortField(env, clazz, field, EVFILT_READ);
-    CHECK_EXCEPTION();
-
-    field = (*env)->GetStaticFieldID(env, clazz, "EVFILT_WRITE", "S");
-    CHECK_ERROR_AND_EXCEPTION(field);
-    (*env)->SetStaticShortField(env, clazz, field, EVFILT_WRITE);
-    CHECK_EXCEPTION();
-
-    field = (*env)->GetStaticFieldID(env, clazz, "SIZEOF_KEVENT", "S");
-    CHECK_ERROR_AND_EXCEPTION(field);
-    (*env)->SetStaticShortField(env, clazz, field, (short) sizeof(struct kevent));
-    CHECK_EXCEPTION();
-
-    field = (*env)->GetStaticFieldID(env, clazz, "FD_OFFSET", "S");
-    CHECK_ERROR_AND_EXCEPTION(field);
-    (*env)->SetStaticShortField(env, clazz, field, (short) offsetof(struct kevent, ident));
-    CHECK_EXCEPTION();
-
-    field = (*env)->GetStaticFieldID(env, clazz, "FILTER_OFFSET", "S");
-    CHECK_ERROR_AND_EXCEPTION(field);
-    (*env)->SetStaticShortField(env, clazz, field, (short) offsetof(struct kevent, filter));
-    CHECK_EXCEPTION();
-    return;
-
-badField:
-    return;
-
-exceptionOccurred:
-    return;
-
-#undef CHECK_EXCEPTION
-#undef CHECK_ERROR_AND_EXCEPTION
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_init(JNIEnv *env, jobject this)
-{
-    int kq = kqueue();
-    if (kq < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: kqueue() failed");
-    }
-    return kq;
-}
-
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_register0(JNIEnv *env, jobject this,
-                                             jint kq, jint fd, jint r, jint w)
-{
-    struct kevent changes[2];
-    struct kevent errors[2];
-    struct timespec dontBlock = {0, 0};
-
-    // if (r) then { register for read } else { unregister for read }
-    // if (w) then { register for write } else { unregister for write }
-    // Ignore errors - they're probably complaints about deleting non-
-    //   added filters - but provide an error array anyway because
-    //   kqueue behaves erratically if some of its registrations fail.
-    EV_SET(&changes[0], fd, EVFILT_READ,  r ? EV_ADD : EV_DELETE, 0, 0, 0);
-    EV_SET(&changes[1], fd, EVFILT_WRITE, w ? EV_ADD : EV_DELETE, 0, 0, 0);
-    kevent(kq, changes, 2, errors, 2, &dontBlock);
-}
-
-JNIEXPORT jint JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_kevent0(JNIEnv *env, jobject this, jint kq,
-                                           jlong kevAddr, jint kevCount,
-                                           jlong timeout)
-{
-    struct kevent *kevs = (struct kevent *)jlong_to_ptr(kevAddr);
-    struct timespec ts;
-    struct timespec *tsp;
-    int result;
-
-    // Java timeout is in milliseconds. Convert to struct timespec.
-    // Java timeout == -1 : wait forever : timespec timeout of NULL
-    // Java timeout == 0  : return immediately : timespec timeout of zero
-    if (timeout >= 0) {
-        // For some indeterminate reason kevent(2) has been found to fail with
-        // an EINVAL error for timeout values greater than or equal to
-        // 100000001000L. To avoid this problem, clamp the timeout arbitrarily
-        // to the maximum value of a 32-bit signed integer which is
-        // approximately 25 days in milliseconds.
-        const jlong timeoutMax = 0x7fffffff; // java.lang.Integer.MAX_VALUE
-        if (timeout > timeoutMax) {
-            timeout = timeoutMax;
-        }
-        ts.tv_sec = timeout / 1000;
-        ts.tv_nsec = (timeout % 1000) * 1000000; //nanosec = 1 million millisec
-        tsp = &ts;
-    } else {
-        tsp = NULL;
-    }
-
-    RESTARTABLE(kevent(kq, NULL, 0, kevs, kevCount, tsp), result);
-    if (result < 0) {
-        JNU_ThrowIOExceptionWithLastError(env,
-            "KQueueArrayWrapper: kevent poll failed");
-    }
-
-    return result;
-}
-
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueueArrayWrapper_interrupt(JNIEnv *env, jclass cls, jint fd)
-{
-    char c = 1;
-    if (1 != write(fd, &c, 1)) {
-        JNU_ThrowIOExceptionWithLastError(env, "KQueueArrayWrapper: interrupt failed");
-    }
-}
-
--- a/src/java.base/macosx/native/libnio/ch/KQueuePort.c	Fri Mar 23 11:18:39 2018 +0530
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-#include "jni.h"
-#include "jni_util.h"
-#include "jvm.h"
-#include "jlong.h"
-#include "nio_util.h"
-
-#include "sun_nio_ch_KQueuePort.h"
-
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_socketpair(JNIEnv* env, jclass clazz, jintArray sv) {
-    int sp[2];
-    if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
-        JNU_ThrowIOExceptionWithLastError(env, "socketpair failed");
-    } else {
-        jint res[2];
-        res[0] = (jint)sp[0];
-        res[1] = (jint)sp[1];
-        (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_interrupt(JNIEnv *env, jclass c, jint fd) {
-    int res;
-    int buf[1];
-    buf[0] = 1;
-    RESTARTABLE(write(fd, buf, 1), res);
-    if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "write failed");
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_drain1(JNIEnv *env, jclass cl, jint fd) {
-    int res;
-    char buf[1];
-    RESTARTABLE(read(fd, buf, 1), res);
-    if (res < 0) {
-        JNU_ThrowIOExceptionWithLastError(env, "drain1 failed");
-    }
-}
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_KQueuePort_close0(JNIEnv *env, jclass c, jint fd) {
-    int res;
-    RESTARTABLE(close(fd), res);
-}
--- a/src/java.base/share/classes/java/io/ByteArrayInputStream.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/io/ByteArrayInputStream.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 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,12 +25,15 @@
 
 package java.io;
 
+import java.util.Arrays;
+import java.util.Objects;
+
 /**
- * A <code>ByteArrayInputStream</code> contains
+ * A {@code ByteArrayInputStream} contains
  * an internal buffer that contains bytes that
  * may be read from the stream. An internal
  * counter keeps track of the next byte to
- * be supplied by the <code>read</code> method.
+ * be supplied by the {@code read} method.
  * <p>
  * Closing a {@code ByteArrayInputStream} has no effect. The methods in
  * this class can be called after the stream has been closed without
@@ -40,15 +43,14 @@
  * @see     java.io.StringBufferInputStream
  * @since   1.0
  */
-public
-class ByteArrayInputStream extends InputStream {
+public class ByteArrayInputStream extends InputStream {
 
     /**
      * An array of bytes that was provided
-     * by the creator of the stream. Elements <code>buf[0]</code>
-     * through <code>buf[count-1]</code> are the
+     * by the creator of the stream. Elements {@code buf[0]}
+     * through {@code buf[count-1]} are the
      * only bytes that can ever be read from the
-     * stream;  element <code>buf[pos]</code> is
+     * stream;  element {@code buf[pos]} is
      * the next byte to be read.
      */
     protected byte buf[];
@@ -56,9 +58,9 @@
     /**
      * The index of the next character to read from the input stream buffer.
      * This value should always be nonnegative
-     * and not larger than the value of <code>count</code>.
+     * and not larger than the value of {@code count}.
      * The next byte to be read from the input stream buffer
-     * will be <code>buf[pos]</code>.
+     * will be {@code buf[pos]}.
      */
     protected int pos;
 
@@ -66,9 +68,9 @@
      * The currently marked position in the stream.
      * ByteArrayInputStream objects are marked at position zero by
      * default when constructed.  They may be marked at another
-     * position within the buffer by the <code>mark()</code> method.
+     * position within the buffer by the {@code mark()} method.
      * The current buffer position is set to this point by the
-     * <code>reset()</code> method.
+     * {@code reset()} method.
      * <p>
      * If no mark has been set, then the value of mark is the offset
      * passed to the constructor (or 0 if the offset was not supplied).
@@ -81,22 +83,22 @@
      * The index one greater than the last valid character in the input
      * stream buffer.
      * This value should always be nonnegative
-     * and not larger than the length of <code>buf</code>.
+     * and not larger than the length of {@code buf}.
      * It  is one greater than the position of
-     * the last byte within <code>buf</code> that
+     * the last byte within {@code buf} that
      * can ever be read  from the input stream buffer.
      */
     protected int count;
 
     /**
-     * Creates a <code>ByteArrayInputStream</code>
-     * so that it  uses <code>buf</code> as its
+     * Creates a {@code ByteArrayInputStream}
+     * so that it  uses {@code buf} as its
      * buffer array.
      * The buffer array is not copied.
-     * The initial value of <code>pos</code>
-     * is <code>0</code> and the initial value
-     * of  <code>count</code> is the length of
-     * <code>buf</code>.
+     * The initial value of {@code pos}
+     * is {@code 0} and the initial value
+     * of  {@code count} is the length of
+     * {@code buf}.
      *
      * @param   buf   the input buffer.
      */
@@ -107,12 +109,12 @@
     }
 
     /**
-     * Creates <code>ByteArrayInputStream</code>
-     * that uses <code>buf</code> as its
-     * buffer array. The initial value of <code>pos</code>
-     * is <code>offset</code> and the initial value
-     * of <code>count</code> is the minimum of <code>offset+length</code>
-     * and <code>buf.length</code>.
+     * Creates {@code ByteArrayInputStream}
+     * that uses {@code buf} as its
+     * buffer array. The initial value of {@code pos}
+     * is {@code offset} and the initial value
+     * of {@code count} is the minimum of {@code offset+length}
+     * and {@code buf.length}.
      * The buffer array is not copied. The buffer's mark is
      * set to the specified offset.
      *
@@ -129,15 +131,15 @@
 
     /**
      * Reads the next byte of data from this input stream. The value
-     * byte is returned as an <code>int</code> in the range
-     * <code>0</code> to <code>255</code>. If no byte is available
+     * byte is returned as an {@code int} in the range
+     * {@code 0} to {@code 255}. If no byte is available
      * because the end of the stream has been reached, the value
-     * <code>-1</code> is returned.
+     * {@code -1} is returned.
      * <p>
-     * This <code>read</code> method
+     * This {@code read} method
      * cannot block.
      *
-     * @return  the next byte of data, or <code>-1</code> if the end of the
+     * @return  the next byte of data, or {@code -1} if the end of the
      *          stream has been reached.
      */
     public synchronized int read() {
@@ -145,40 +147,30 @@
     }
 
     /**
-     * Reads up to <code>len</code> bytes of data into an array of bytes
-     * from this input stream.
-     * If <code>pos</code> equals <code>count</code>,
-     * then <code>-1</code> is returned to indicate
-     * end of file. Otherwise, the  number <code>k</code>
-     * of bytes read is equal to the smaller of
-     * <code>len</code> and <code>count-pos</code>.
-     * If <code>k</code> is positive, then bytes
-     * <code>buf[pos]</code> through <code>buf[pos+k-1]</code>
-     * are copied into <code>b[off]</code>  through
-     * <code>b[off+k-1]</code> in the manner performed
-     * by <code>System.arraycopy</code>. The
-     * value <code>k</code> is added into <code>pos</code>
-     * and <code>k</code> is returned.
+     * Reads up to {@code len} bytes of data into an array of bytes from this
+     * input stream.  If {@code pos} equals {@code count}, then {@code -1} is
+     * returned to indicate end of file.  Otherwise, the  number {@code k} of
+     * bytes read is equal to the smaller of {@code len} and {@code count-pos}.
+     * If {@code k} is positive, then bytes {@code buf[pos]} through
+     * {@code buf[pos+k-1]} are copied into {@code b[off]} through
+     * {@code b[off+k-1]} in the manner performed by {@code System.arraycopy}.
+     * The value {@code k} is added into {@code pos} and {@code k} is returned.
      * <p>
-     * This <code>read</code> method cannot block.
+     * This {@code read} method cannot block.
      *
      * @param   b     the buffer into which the data is read.
-     * @param   off   the start offset in the destination array <code>b</code>
+     * @param   off   the start offset in the destination array {@code b}
      * @param   len   the maximum number of bytes read.
      * @return  the total number of bytes read into the buffer, or
-     *          <code>-1</code> if there is no more data because the end of
+     *          {@code -1} if there is no more data because the end of
      *          the stream has been reached.
-     * @exception  NullPointerException If <code>b</code> is <code>null</code>.
-     * @exception  IndexOutOfBoundsException If <code>off</code> is negative,
-     * <code>len</code> is negative, or <code>len</code> is greater than
-     * <code>b.length - off</code>
+     * @throws  NullPointerException If {@code b} is {@code null}.
+     * @throws  IndexOutOfBoundsException If {@code off} is negative,
+     * {@code len} is negative, or {@code len} is greater than
+     * {@code b.length - off}
      */
     public synchronized int read(byte b[], int off, int len) {
-        if (b == null) {
-            throw new NullPointerException();
-        } else if (off < 0 || len < 0 || len > b.length - off) {
-            throw new IndexOutOfBoundsException();
-        }
+        Objects.checkFromIndexSize(off, len, b.length);
 
         if (pos >= count) {
             return -1;
@@ -196,14 +188,32 @@
         return len;
     }
 
+    public synchronized byte[] readAllBytes() {
+        byte[] result = Arrays.copyOfRange(buf, pos, count);
+        pos = count;
+        return result;
+    }
+
+    public int readNBytes(byte[] b, int off, int len) {
+        int n = read(b, off, len);
+        return n == -1 ? 0 : n;
+    }
+
+    public synchronized long transferTo(OutputStream out) throws IOException {
+        int len = count - pos;
+        out.write(buf, pos, len);
+        pos = count;
+        return len;
+    }
+
     /**
-     * Skips <code>n</code> bytes of input from this input stream. Fewer
+     * Skips {@code n} bytes of input from this input stream. Fewer
      * bytes might be skipped if the end of the input stream is reached.
-     * The actual number <code>k</code>
+     * The actual number {@code k}
      * of bytes to be skipped is equal to the smaller
-     * of <code>n</code> and  <code>count-pos</code>.
-     * The value <code>k</code> is added into <code>pos</code>
-     * and <code>k</code> is returned.
+     * of {@code n} and  {@code count-pos}.
+     * The value {@code k} is added into {@code pos}
+     * and {@code k} is returned.
      *
      * @param   n   the number of bytes to be skipped.
      * @return  the actual number of bytes skipped.
@@ -222,7 +232,7 @@
      * Returns the number of remaining bytes that can be read (or skipped over)
      * from this input stream.
      * <p>
-     * The value returned is <code>count&nbsp;- pos</code>,
+     * The value returned is {@code count - pos},
      * which is the number of bytes remaining to be read from the input buffer.
      *
      * @return  the number of remaining bytes that can be read (or skipped
@@ -233,9 +243,9 @@
     }
 
     /**
-     * Tests if this <code>InputStream</code> supports mark/reset. The
-     * <code>markSupported</code> method of <code>ByteArrayInputStream</code>
-     * always returns <code>true</code>.
+     * Tests if this {@code InputStream} supports mark/reset. The
+     * {@code markSupported} method of {@code ByteArrayInputStream}
+     * always returns {@code true}.
      *
      * @since   1.1
      */
@@ -253,7 +263,7 @@
      * offset passed to the constructor (or 0 if the offset was not
      * supplied).
      *
-     * <p> Note: The <code>readAheadLimit</code> for this class
+     * <p> Note: The {@code readAheadLimit} for this class
      *  has no meaning.
      *
      * @since   1.1
--- a/src/java.base/share/classes/java/lang/invoke/ProxyClassesDumper.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/lang/invoke/ProxyClassesDumper.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 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
@@ -30,7 +30,6 @@
 import java.nio.file.Files;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Objects;
@@ -63,7 +62,7 @@
         }
         try {
             path = path.trim();
-            final Path dir = Paths.get(path.length() == 0 ? "." : path);
+            final Path dir = Path.of(path.length() == 0 ? "." : path);
             AccessController.doPrivileged(new PrivilegedAction<>() {
                     @Override
                     public Void run() {
--- a/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/lang/reflect/ProxyGenerator.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -34,7 +34,6 @@
 import java.lang.reflect.Method;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -346,11 +345,11 @@
                         int i = name.lastIndexOf('.');
                         Path path;
                         if (i > 0) {
-                            Path dir = Paths.get(name.substring(0, i).replace('.', File.separatorChar));
+                            Path dir = Path.of(name.substring(0, i).replace('.', File.separatorChar));
                             Files.createDirectories(dir);
                             path = dir.resolve(name.substring(i+1, name.length()) + ".class");
                         } else {
-                            path = Paths.get(name + ".class");
+                            path = Path.of(name + ".class");
                         }
                         Files.write(path, classFile);
                         return null;
--- a/src/java.base/share/classes/java/nio/channels/DatagramChannel.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/nio/channels/DatagramChannel.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2017, 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
@@ -279,6 +279,9 @@
      *
      * @return  This datagram channel
      *
+     * @throws  AlreadyConnectedException
+     *          If this channel is already connected
+     *
      * @throws  ClosedChannelException
      *          If this channel is closed
      *
@@ -292,6 +295,12 @@
      *          closing the channel and setting the current thread's
      *          interrupt status
      *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     *
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     *
      * @throws  SecurityException
      *          If a security manager has been installed
      *          and it does not permit access to the given remote address
@@ -444,6 +453,10 @@
      *           zero if there was insufficient room for the datagram in the
      *           underlying output buffer
      *
+     * @throws  AlreadyConnectedException
+     *          If this channel is connected to a different address
+     *          from that specified by {@code target}
+     *
      * @throws  ClosedChannelException
      *          If this channel is closed
      *
@@ -457,6 +470,12 @@
      *          closing the channel and setting the current thread's
      *          interrupt status
      *
+     * @throws  UnresolvedAddressException
+     *          If the given remote address is not fully resolved
+     *
+     * @throws  UnsupportedAddressTypeException
+     *          If the type of the given remote address is not supported
+     *
      * @throws  SecurityException
      *          If a security manager has been installed
      *          and it does not permit datagrams to be sent
--- a/src/java.base/share/classes/java/nio/file/Path.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/nio/file/Path.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, 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
@@ -28,6 +28,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.net.URI;
+import java.nio.file.spi.FileSystemProvider;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
 
@@ -93,13 +94,125 @@
  * multiple concurrent threads.
  *
  * @since 1.7
- * @see Paths
  */
 
 public interface Path
     extends Comparable<Path>, Iterable<Path>, Watchable
 {
     /**
+     * Returns a {@code Path} by converting a path string, or a sequence of
+     * strings that when joined form a path string. If {@code more} does not
+     * specify any elements then the value of the {@code first} parameter is
+     * the path string to convert. If {@code more} specifies one or more
+     * elements then each non-empty string, including {@code first}, is
+     * considered to be a sequence of name elements and is joined to form a
+     * path string. The details as to how the Strings are joined is provider
+     * specific but typically they will be joined using the
+     * {@link FileSystem#getSeparator name-separator} as the separator.
+     * For example, if the name separator is "{@code /}" and
+     * {@code getPath("/foo","bar","gus")} is invoked, then the path string
+     * {@code "/foo/bar/gus"} is converted to a {@code Path}. A {@code Path}
+     * representing an empty path is returned if {@code first} is the empty
+     * string and {@code more} does not contain any non-empty strings.
+     *
+     * <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
+     * getPath} method of the {@link FileSystems#getDefault default} {@link
+     * FileSystem}.
+     *
+     * <p> Note that while this method is very convenient, using it will imply
+     * an assumed reference to the default {@code FileSystem} and limit the
+     * utility of the calling code. Hence it should not be used in library code
+     * intended for flexible reuse. A more flexible alternative is to use an
+     * existing {@code Path} instance as an anchor, such as:
+     * <pre>{@code
+     *     Path dir = ...
+     *     Path path = dir.resolve("file");
+     * }</pre>
+     *
+     * @param   first
+     *          the path string or initial part of the path string
+     * @param   more
+     *          additional strings to be joined to form the path string
+     *
+     * @return  the resulting {@code Path}
+     *
+     * @throws  InvalidPathException
+     *          if the path string cannot be converted to a {@code Path}
+     *
+     * @see FileSystem#getPath
+     *
+     * @since 11
+     */
+    public static Path of(String first, String... more) {
+        return FileSystems.getDefault().getPath(first, more);
+    }
+
+    /**
+     * Returns a {@code Path} by converting a URI.
+     *
+     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
+     * installed} providers to locate the provider that is identified by the
+     * URI {@link URI#getScheme scheme} of the given URI. URI schemes are
+     * compared without regard to case. If the provider is found then its {@link
+     * FileSystemProvider#getPath getPath} method is invoked to convert the
+     * URI.
+     *
+     * <p> In the case of the default provider, identified by the URI scheme
+     * "file", the given URI has a non-empty path component, and undefined query
+     * and fragment components. Whether the authority component may be present
+     * is platform specific. The returned {@code Path} is associated with the
+     * {@link FileSystems#getDefault default} file system.
+     *
+     * <p> The default provider provides a similar <em>round-trip</em> guarantee
+     * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
+     * is guaranteed that
+     * <blockquote>{@code
+     * Path.of(}<i>p</i>{@code .}{@link Path#toUri() toUri}{@code ()).equals(}
+     * <i>p</i>{@code .}{@link Path#toAbsolutePath() toAbsolutePath}{@code ())}
+     * </blockquote>
+     * so long as the original {@code Path}, the {@code URI}, and the new {@code
+     * Path} are all created in (possibly different invocations of) the same
+     * Java virtual machine. Whether other providers make any guarantees is
+     * provider specific and therefore unspecified.
+     *
+     * @param   uri
+     *          the URI to convert
+     *
+     * @return  the resulting {@code Path}
+     *
+     * @throws  IllegalArgumentException
+     *          if preconditions on the {@code uri} parameter do not hold. The
+     *          format of the URI is provider specific.
+     * @throws  FileSystemNotFoundException
+     *          The file system, identified by the URI, does not exist and
+     *          cannot be created automatically, or the provider identified by
+     *          the URI's scheme component is not installed
+     * @throws  SecurityException
+     *          if a security manager is installed and it denies an unspecified
+     *          permission to access the file system
+     *
+     * @since 11
+     */
+    public static Path of(URI uri) {
+        String scheme =  uri.getScheme();
+        if (scheme == null)
+            throw new IllegalArgumentException("Missing scheme");
+
+        // check for default provider to avoid loading of installed providers
+        if (scheme.equalsIgnoreCase("file"))
+            return FileSystems.getDefault().provider().getPath(uri);
+
+        // try to find provider
+        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
+            if (provider.getScheme().equalsIgnoreCase(scheme)) {
+                return provider.getPath(uri);
+            }
+        }
+
+        throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
+    }
+
+    /**
      * Returns the file system that created this object.
      *
      * @return  the file system that created this object
@@ -527,7 +640,7 @@
      * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
      * is guaranteed that
      * <blockquote>
-     * {@link Paths#get(URI) Paths.get}{@code (}<i>p</i>{@code .toUri()).equals(}<i>p</i>
+     * {@link Path#of(URI) Path.of}{@code (}<i>p</i>{@code .toUri()).equals(}<i>p</i>
      * {@code .}{@link #toAbsolutePath() toAbsolutePath}{@code ())}
      * </blockquote>
      * so long as the original {@code Path}, the {@code URI}, and the new {@code
--- a/src/java.base/share/classes/java/nio/file/Paths.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/nio/file/Paths.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2011, 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
@@ -32,7 +32,13 @@
  * This class consists exclusively of static methods that return a {@link Path}
  * by converting a path string or {@link URI}.
  *
+ * @apiNote
+ * It is recommended to obtain a {@code Path} via the {@code Path.of} methods
+ * instead of via the {@code get} methods defined in this class as this class
+ * may be deprecated in a future release.
+ *
  * @since 1.7
+ * @see Path
  */
 
 public final class Paths {
@@ -40,33 +46,11 @@
 
     /**
      * Converts a path string, or a sequence of strings that when joined form
-     * a path string, to a {@code Path}. If {@code more} does not specify any
-     * elements then the value of the {@code first} parameter is the path string
-     * to convert. If {@code more} specifies one or more elements then each
-     * non-empty string, including {@code first}, is considered to be a sequence
-     * of name elements (see {@link Path}) and is joined to form a path string.
-     * The details as to how the Strings are joined is provider specific but
-     * typically they will be joined using the {@link FileSystem#getSeparator
-     * name-separator} as the separator. For example, if the name separator is
-     * "{@code /}" and {@code getPath("/foo","bar","gus")} is invoked, then the
-     * path string {@code "/foo/bar/gus"} is converted to a {@code Path}.
-     * A {@code Path} representing an empty path is returned if {@code first}
-     * is the empty string and {@code more} does not contain any non-empty
-     * strings.
+     * a path string, to a {@code Path}.
      *
-     * <p> The {@code Path} is obtained by invoking the {@link FileSystem#getPath
-     * getPath} method of the {@link FileSystems#getDefault default} {@link
-     * FileSystem}.
-     *
-     * <p> Note that while this method is very convenient, using it will imply
-     * an assumed reference to the default {@code FileSystem} and limit the
-     * utility of the calling code. Hence it should not be used in library code
-     * intended for flexible reuse. A more flexible alternative is to use an
-     * existing {@code Path} instance as an anchor, such as:
-     * <pre>
-     *     Path dir = ...
-     *     Path path = dir.resolve("file");
-     * </pre>
+     * @implSpec
+     * This method simply invokes {@link Path#of(String,String...)
+     * Path.of(String, String...)} with the given parameters.
      *
      * @param   first
      *          the path string or initial part of the path string
@@ -79,38 +63,17 @@
      *          if the path string cannot be converted to a {@code Path}
      *
      * @see FileSystem#getPath
+     * @see Path#of(String,String...)
      */
     public static Path get(String first, String... more) {
-        return FileSystems.getDefault().getPath(first, more);
+        return Path.of(first, more);
     }
 
     /**
      * Converts the given URI to a {@link Path} object.
      *
-     * <p> This method iterates over the {@link FileSystemProvider#installedProviders()
-     * installed} providers to locate the provider that is identified by the
-     * URI {@link URI#getScheme scheme} of the given URI. URI schemes are
-     * compared without regard to case. If the provider is found then its {@link
-     * FileSystemProvider#getPath getPath} method is invoked to convert the
-     * URI.
-     *
-     * <p> In the case of the default provider, identified by the URI scheme
-     * "file", the given URI has a non-empty path component, and undefined query
-     * and fragment components. Whether the authority component may be present
-     * is platform specific. The returned {@code Path} is associated with the
-     * {@link FileSystems#getDefault default} file system.
-     *
-     * <p> The default provider provides a similar <em>round-trip</em> guarantee
-     * to the {@link java.io.File} class. For a given {@code Path} <i>p</i> it
-     * is guaranteed that
-     * <blockquote>{@code
-     * Paths.get(}<i>p</i>{@code .}{@link Path#toUri() toUri}{@code ()).equals(}
-     * <i>p</i>{@code .}{@link Path#toAbsolutePath() toAbsolutePath}{@code ())}
-     * </blockquote>
-     * so long as the original {@code Path}, the {@code URI}, and the new {@code
-     * Path} are all created in (possibly different invocations of) the same
-     * Java virtual machine. Whether other providers make any guarantees is
-     * provider specific and therefore unspecified.
+     * @implSpec
+     * This method simply invokes {@link Path#of(URI) * Path.of(URI)} with the given parameter.
      *
      * @param   uri
      *          the URI to convert
@@ -127,23 +90,10 @@
      * @throws  SecurityException
      *          if a security manager is installed and it denies an unspecified
      *          permission to access the file system
+     *
+     * @see Path#of(URI)
      */
     public static Path get(URI uri) {
-        String scheme =  uri.getScheme();
-        if (scheme == null)
-            throw new IllegalArgumentException("Missing scheme");
-
-        // check for default provider to avoid loading of installed providers
-        if (scheme.equalsIgnoreCase("file"))
-            return FileSystems.getDefault().provider().getPath(uri);
-
-        // try to find provider
-        for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
-            if (provider.getScheme().equalsIgnoreCase(scheme)) {
-                return provider.getPath(uri);
-            }
-        }
-
-        throw new FileSystemNotFoundException("Provider \"" + scheme + "\" not installed");
+        return Path.of(uri);
     }
 }
--- a/src/java.base/share/classes/java/nio/file/TempFileHelper.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/nio/file/TempFileHelper.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -46,7 +46,7 @@
 
     // temporary directory location
     private static final Path tmpdir =
-        Paths.get(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
+        Path.of(GetPropertyAction.privilegedGetProperty("java.io.tmpdir"));
 
     private static final boolean isPosix =
         FileSystems.getDefault().supportedFileAttributeViews().contains("posix");
--- a/src/java.base/share/classes/java/util/AbstractSet.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/util/AbstractSet.java	Fri Mar 23 11:14:43 2018 -0700
@@ -93,9 +93,7 @@
             return false;
         try {
             return containsAll(c);
-        } catch (ClassCastException unused)   {
-            return false;
-        } catch (NullPointerException unused) {
+        } catch (ClassCastException | NullPointerException unused) {
             return false;
         }
     }
--- a/src/java.base/share/classes/java/util/ImmutableCollections.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/util/ImmutableCollections.java	Fri Mar 23 11:14:43 2018 -0700
@@ -70,46 +70,297 @@
 
     static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); }
 
-    // ---------- List Implementations ----------
-
-    abstract static class AbstractImmutableList<E> extends AbstractList<E>
-                                                implements RandomAccess, Serializable {
+    static abstract class AbstractImmutableCollection<E> extends AbstractCollection<E> {
+        // all mutating methods throw UnsupportedOperationException
         @Override public boolean add(E e) { throw uoe(); }
         @Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
-        @Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
         @Override public void    clear() { throw uoe(); }
         @Override public boolean remove(Object o) { throw uoe(); }
         @Override public boolean removeAll(Collection<?> c) { throw uoe(); }
         @Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
-        @Override public void    replaceAll(UnaryOperator<E> operator) { throw uoe(); }
         @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
-        @Override public void    sort(Comparator<? super E> c) { throw uoe(); }
     }
 
-    static final class List0<E> extends AbstractImmutableList<E> {
-        private static final List0<?> INSTANCE = new List0<>();
+    // ---------- List Implementations ----------
 
-        @SuppressWarnings("unchecked")
-        static <T> List0<T> instance() {
-            return (List0<T>) INSTANCE;
+    @SuppressWarnings("unchecked")
+    static <E> List<E> emptyList() {
+        return (List<E>) ListN.EMPTY_LIST;
+    }
+
+    static abstract class AbstractImmutableList<E> extends AbstractImmutableCollection<E>
+            implements List<E>, RandomAccess {
+
+        // all mutating methods throw UnsupportedOperationException
+        @Override public void    add(int index, E element) { throw uoe(); }
+        @Override public boolean addAll(int index, Collection<? extends E> c) { throw uoe(); }
+        @Override public E       remove(int index) { throw uoe(); }
+        @Override public void    replaceAll(UnaryOperator<E> operator) { throw uoe(); }
+        @Override public E       set(int index, E element) { throw uoe(); }
+        @Override public void    sort(Comparator<? super E> c) { throw uoe(); }
+
+        @Override
+        public List<E> subList(int fromIndex, int toIndex) {
+            int size = size();
+            subListRangeCheck(fromIndex, toIndex, size);
+            return SubList.fromList(this, fromIndex, toIndex);
         }
 
-        private List0() { }
+        static void subListRangeCheck(int fromIndex, int toIndex, int size) {
+            if (fromIndex < 0)
+                throw new IndexOutOfBoundsException("fromIndex = " + fromIndex);
+            if (toIndex > size)
+                throw new IndexOutOfBoundsException("toIndex = " + toIndex);
+            if (fromIndex > toIndex)
+                throw new IllegalArgumentException("fromIndex(" + fromIndex +
+                        ") > toIndex(" + toIndex + ")");
+        }
+
+        @Override
+        public Iterator<E> iterator() {
+            return new ListItr<E>(this, size());
+        }
+
+        @Override
+        public ListIterator<E> listIterator() {
+            return listIterator(0);
+        }
+
+        @Override
+        public ListIterator<E> listIterator(final int index) {
+            int size = size();
+            if (index < 0 || index > size) {
+                throw outOfBounds(index);
+            }
+            return new ListItr<E>(this, size, index);
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            }
+
+            if (!(o instanceof List)) {
+                return false;
+            }
+
+            Iterator<?> oit = ((List<?>) o).iterator();
+            for (int i = 0, s = size(); i < s; i++) {
+                if (!oit.hasNext() || !get(i).equals(oit.next())) {
+                    return false;
+                }
+            }
+            return !oit.hasNext();
+        }
+
+        @Override
+        public int indexOf(Object o) {
+            Objects.requireNonNull(o);
+            for (int i = 0, s = size(); i < s; i++) {
+                if (o.equals(get(i))) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        @Override
+        public int lastIndexOf(Object o) {
+            Objects.requireNonNull(o);
+            for (int i = size() - 1; i >= 0; i--) {
+                if (o.equals(get(i))) {
+                    return i;
+                }
+            }
+            return -1;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 1;
+            for (int i = 0, s = size(); i < s; i++) {
+                hash = 31 * hash + get(i).hashCode();
+            }
+            return hash;
+        }
+
+        @Override
+        public boolean contains(Object o) {
+            return indexOf(o) >= 0;
+        }
+
+        IndexOutOfBoundsException outOfBounds(int index) {
+            return new IndexOutOfBoundsException("Index: " + index + " Size: " + size());
+        }
+    }
+
+    static final class ListItr<E> implements ListIterator<E> {
+
+        @Stable
+        private final List<E> list;
+
+        @Stable
+        private final int size;
+
+        private int cursor;
+
+        ListItr(List<E> list, int size) {
+            this(list, size, 0);
+        }
+
+        ListItr(List<E> list, int size, int index) {
+            this.list = list;
+            this.size = size;
+            this.cursor = index;
+        }
+
+        public boolean hasNext() {
+            return cursor != size;
+        }
+
+        public E next() {
+            try {
+                int i = cursor;
+                E next = list.get(i);
+                cursor = i + 1;
+                return next;
+            } catch (IndexOutOfBoundsException e) {
+                throw new NoSuchElementException();
+            }
+        }
+
+        public void remove() {
+            throw uoe();
+        }
+
+        public boolean hasPrevious() {
+            return cursor != 0;
+        }
+
+        public E previous() {
+            try {
+                int i = cursor - 1;
+                E previous = list.get(i);
+                cursor = i;
+                return previous;
+            } catch (IndexOutOfBoundsException e) {
+                throw new NoSuchElementException();
+            }
+        }
+
+        public int nextIndex() {
+            return cursor;
+        }
+
+        public int previousIndex() {
+            return cursor - 1;
+        }
+
+        public void set(E e) {
+            throw uoe();
+        }
+
+        public void add(E e) {
+            throw uoe();
+        }
+    }
+
+    static final class SubList<E> extends AbstractImmutableList<E>
+            implements RandomAccess {
+
+        @Stable
+        private final List<E> root;
+
+        @Stable
+        private final int offset;
+
+        @Stable
+        private final int size;
+
+        private SubList(List<E> root, int offset, int size) {
+            this.root = root;
+            this.offset = offset;
+            this.size = size;
+        }
+
+        /**
+         * Constructs a sublist of another SubList.
+         */
+        static <E> SubList<E> fromSubList(SubList<E> parent, int fromIndex, int toIndex) {
+            return new SubList<E>(parent.root, parent.offset + fromIndex, toIndex - fromIndex);
+        }
+
+        /**
+         * Constructs a sublist of an arbitrary AbstractImmutableList, which is
+         * not a SubList itself.
+         */
+        static <E> SubList<E> fromList(List<E> list, int fromIndex, int toIndex) {
+            return new SubList<E>(list, fromIndex, toIndex - fromIndex);
+        }
+
+        public E get(int index) {
+            Objects.checkIndex(index, size);
+            return root.get(offset + index);
+        }
+
+        public int size() {
+            return size;
+        }
+
+        public Iterator<E> iterator() {
+            return new ListItr<E>(this, size());
+        }
+
+        public ListIterator<E> listIterator(int index) {
+            rangeCheck(index);
+            return new ListItr<E>(this, size(), index);
+        }
+
+        public List<E> subList(int fromIndex, int toIndex) {
+            subListRangeCheck(fromIndex, toIndex, size);
+            return SubList.fromSubList(this, fromIndex, toIndex);
+        }
+
+        private void rangeCheck(int index) {
+            if (index < 0 || index > size) {
+                throw outOfBounds(index);
+            }
+        }
+    }
+
+    static final class List12<E> extends AbstractImmutableList<E>
+            implements Serializable {
+
+        @Stable
+        private final E e0;
+
+        @Stable
+        private final E e1;
+
+        List12(E e0) {
+            this.e0 = Objects.requireNonNull(e0);
+            this.e1 = null;
+        }
+
+        List12(E e0, E e1) {
+            this.e0 = Objects.requireNonNull(e0);
+            this.e1 = Objects.requireNonNull(e1);
+        }
 
         @Override
         public int size() {
-            return 0;
+            return e1 != null ? 2 : 1;
         }
 
         @Override
         public E get(int index) {
-            Objects.checkIndex(index, 0); // always throws IndexOutOfBoundsException
-            return null;                  // but the compiler doesn't know this
-        }
-
-        @Override
-        public Iterator<E> iterator() {
-            return Collections.emptyIterator();
+            if (index == 0) {
+                return e0;
+            } else if (index == 1 && e1 != null) {
+                return e1;
+            }
+            throw outOfBounds(index);
         }
 
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
@@ -117,111 +368,20 @@
         }
 
         private Object writeReplace() {
-            return new CollSer(CollSer.IMM_LIST);
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            Objects.requireNonNull(o);
-            return false;
-        }
-
-        @Override
-        public boolean containsAll(Collection<?> o) {
-            return o.isEmpty(); // implicit nullcheck of o
-        }
-
-        @Override
-        public int hashCode() {
-            return 1;
-        }
-    }
-
-    static final class List1<E> extends AbstractImmutableList<E> {
-        @Stable
-        private final E e0;
-
-        List1(E e0) {
-            this.e0 = Objects.requireNonNull(e0);
-        }
-
-        @Override
-        public int size() {
-            return 1;
-        }
-
-        @Override
-        public E get(int index) {
-            Objects.checkIndex(index, 1);
-            return e0;
-        }
-
-        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            throw new InvalidObjectException("not serial proxy");
-        }
-
-        private Object writeReplace() {
-            return new CollSer(CollSer.IMM_LIST, e0);
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            return o.equals(e0); // implicit nullcheck of o
-        }
-
-        @Override
-        public int hashCode() {
-            return 31 + e0.hashCode();
-        }
-    }
-
-    static final class List2<E> extends AbstractImmutableList<E> {
-        @Stable
-        private final E e0;
-        @Stable
-        private final E e1;
-
-        List2(E e0, E e1) {
-            this.e0 = Objects.requireNonNull(e0);
-            this.e1 = Objects.requireNonNull(e1);
-        }
-
-        @Override
-        public int size() {
-            return 2;
-        }
-
-        @Override
-        public E get(int index) {
-            Objects.checkIndex(index, 2);
-            if (index == 0) {
-                return e0;
-            } else { // index == 1
-                return e1;
+            if (e1 == null) {
+                return new CollSer(CollSer.IMM_LIST, e0);
+            } else {
+                return new CollSer(CollSer.IMM_LIST, e0, e1);
             }
         }
 
-        @Override
-        public boolean contains(Object o) {
-            return o.equals(e0) || o.equals(e1); // implicit nullcheck of o
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 31 + e0.hashCode();
-            return 31 * hash + e1.hashCode();
-        }
-
-        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            throw new InvalidObjectException("not serial proxy");
-        }
-
-        private Object writeReplace() {
-            return new CollSer(CollSer.IMM_LIST, e0, e1);
-        }
     }
 
-    static final class ListN<E> extends AbstractImmutableList<E> {
+    static final class ListN<E> extends AbstractImmutableList<E>
+            implements Serializable {
+
+        static final List<?> EMPTY_LIST = new ListN<>();
+
         @Stable
         private final E[] elements;
 
@@ -233,7 +393,12 @@
             for (int i = 0; i < input.length; i++) {
                 tmp[i] = Objects.requireNonNull(input[i]);
             }
-            this.elements = tmp;
+            elements = tmp;
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return size() == 0;
         }
 
         @Override
@@ -243,29 +408,9 @@
 
         @Override
         public E get(int index) {
-            Objects.checkIndex(index, elements.length);
             return elements[index];
         }
 
-        @Override
-        public boolean contains(Object o) {
-            for (E e : elements) {
-                if (o.equals(e)) { // implicit nullcheck of o
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            int hash = 1;
-            for (E e : elements) {
-                hash = 31 * hash + e.hashCode();
-            }
-            return hash;
-        }
-
         private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
             throw new InvalidObjectException("not serial proxy");
         }
@@ -277,105 +422,52 @@
 
     // ---------- Set Implementations ----------
 
-    abstract static class AbstractImmutableSet<E> extends AbstractSet<E> implements Serializable {
-        @Override public boolean add(E e) { throw uoe(); }
-        @Override public boolean addAll(Collection<? extends E> c) { throw uoe(); }
-        @Override public void    clear() { throw uoe(); }
-        @Override public boolean remove(Object o) { throw uoe(); }
-        @Override public boolean removeAll(Collection<?> c) { throw uoe(); }
-        @Override public boolean removeIf(Predicate<? super E> filter) { throw uoe(); }
-        @Override public boolean retainAll(Collection<?> c) { throw uoe(); }
-    }
-
-    static final class Set0<E> extends AbstractImmutableSet<E> {
-        private static final Set0<?> INSTANCE = new Set0<>();
-
-        @SuppressWarnings("unchecked")
-        static <T> Set0<T> instance() {
-            return (Set0<T>) INSTANCE;
-        }
-
-        private Set0() { }
+    static abstract class AbstractImmutableSet<E> extends AbstractImmutableCollection<E>
+            implements Set<E> {
 
         @Override
-        public int size() {
-            return 0;
+        public boolean equals(Object o) {
+            if (o == this) {
+                return true;
+            } else if (!(o instanceof Set)) {
+                return false;
+            }
+
+            Collection<?> c = (Collection<?>) o;
+            if (c.size() != size()) {
+                return false;
+            }
+            for (Object e : c) {
+                if (e == null || !contains(e)) {
+                    return false;
+                }
+            }
+            return true;
         }
 
         @Override
-        public boolean contains(Object o) {
-            Objects.requireNonNull(o);
-            return false;
-        }
-
-        @Override
-        public boolean containsAll(Collection<?> o) {
-            return o.isEmpty(); // implicit nullcheck of o
-        }
-
-        @Override
-        public Iterator<E> iterator() {
-            return Collections.emptyIterator();
-        }
-
-        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            throw new InvalidObjectException("not serial proxy");
-        }
-
-        private Object writeReplace() {
-            return new CollSer(CollSer.IMM_SET);
-        }
-
-        @Override
-        public int hashCode() {
-            return 0;
-        }
+        public abstract int hashCode();
     }
 
-    static final class Set1<E> extends AbstractImmutableSet<E> {
-        @Stable
-        private final E e0;
-
-        Set1(E e0) {
-            this.e0 = Objects.requireNonNull(e0);
-        }
-
-        @Override
-        public int size() {
-            return 1;
-        }
-
-        @Override
-        public boolean contains(Object o) {
-            return o.equals(e0); // implicit nullcheck of o
-        }
-
-        @Override
-        public Iterator<E> iterator() {
-            return Collections.singletonIterator(e0);
-        }
-
-        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            throw new InvalidObjectException("not serial proxy");
-        }
-
-        private Object writeReplace() {
-            return new CollSer(CollSer.IMM_SET, e0);
-        }
-
-        @Override
-        public int hashCode() {
-            return e0.hashCode();
-        }
+    @SuppressWarnings("unchecked")
+    static <E> Set<E> emptySet() {
+        return (Set<E>) SetN.EMPTY_SET;
     }
 
-    static final class Set2<E> extends AbstractImmutableSet<E> {
+    static final class Set12<E> extends AbstractImmutableSet<E>
+            implements Serializable {
+
         @Stable
         final E e0;
         @Stable
         final E e1;
 
-        Set2(E e0, E e1) {
+        Set12(E e0) {
+            this.e0 = Objects.requireNonNull(e0);
+            this.e1 = null;
+        }
+
+        Set12(E e0, E e1) {
             if (e0.equals(Objects.requireNonNull(e1))) { // implicit nullcheck of e0
                 throw new IllegalArgumentException("duplicate element: " + e0);
             }
@@ -391,7 +483,7 @@
 
         @Override
         public int size() {
-            return 2;
+            return (e1 == null) ? 1 : 2;
         }
 
         @Override
@@ -401,26 +493,26 @@
 
         @Override
         public int hashCode() {
-            return e0.hashCode() + e1.hashCode();
+            return e0.hashCode() + (e1 == null ? 0 : e1.hashCode());
         }
 
         @Override
         public Iterator<E> iterator() {
-            return new Iterator<E>() {
-                private int idx = 0;
+            return new Iterator<>() {
+                private int idx = size();
 
                 @Override
                 public boolean hasNext() {
-                    return idx < 2;
+                    return idx > 0;
                 }
 
                 @Override
                 public E next() {
-                    if (idx == 0) {
+                    if (idx == 1) {
+                        idx = 0;
+                        return e0;
+                    } else if (idx == 2) {
                         idx = 1;
-                        return e0;
-                    } else if (idx == 1) {
-                        idx = 2;
                         return e1;
                     } else {
                         throw new NoSuchElementException();
@@ -434,7 +526,11 @@
         }
 
         private Object writeReplace() {
-            return new CollSer(CollSer.IMM_SET, e0, e1);
+            if (e1 == null) {
+                return new CollSer(CollSer.IMM_SET, e0);
+            } else {
+                return new CollSer(CollSer.IMM_SET, e0, e1);
+            }
         }
     }
 
@@ -444,7 +540,11 @@
      * least one null is always present.
      * @param <E> the element type
      */
-    static final class SetN<E> extends AbstractImmutableSet<E> {
+    static final class SetN<E> extends AbstractImmutableSet<E>
+            implements Serializable {
+
+        static final Set<?> EMPTY_SET = new SetN<>();
+
         @Stable
         final E[] elements;
         @Stable
@@ -474,12 +574,13 @@
 
         @Override
         public boolean contains(Object o) {
-            return probe(o) >= 0; // implicit nullcheck of o
+            Objects.requireNonNull(o);
+            return size > 0 && probe(o) >= 0;
         }
 
         @Override
         public Iterator<E> iterator() {
-            return new Iterator<E>() {
+            return new Iterator<>() {
                 private int idx = 0;
 
                 @Override
@@ -549,6 +650,11 @@
 
     // ---------- Map Implementations ----------
 
+    @SuppressWarnings("unchecked")
+    static <K,V> Map<K,V> emptyMap() {
+        return (Map<K,V>) MapN.EMPTY_MAP;
+    }
+
     abstract static class AbstractImmutableMap<K,V> extends AbstractMap<K,V> implements Serializable {
         @Override public void clear() { throw uoe(); }
         @Override public V compute(K key, BiFunction<? super K,? super V,? extends V> rf) { throw uoe(); }
@@ -565,47 +671,6 @@
         @Override public void replaceAll(BiFunction<? super K,? super V,? extends V> f) { throw uoe(); }
     }
 
-    static final class Map0<K,V> extends AbstractImmutableMap<K,V> {
-        private static final Map0<?,?> INSTANCE = new Map0<>();
-
-        @SuppressWarnings("unchecked")
-        static <K,V> Map0<K,V> instance() {
-            return (Map0<K,V>) INSTANCE;
-        }
-
-        private Map0() { }
-
-        @Override
-        public Set<Map.Entry<K,V>> entrySet() {
-            return Set.of();
-        }
-
-        @Override
-        public boolean containsKey(Object o) {
-            Objects.requireNonNull(o);
-            return false;
-        }
-
-        @Override
-        public boolean containsValue(Object o) {
-            Objects.requireNonNull(o);
-            return false;
-        }
-
-        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-            throw new InvalidObjectException("not serial proxy");
-        }
-
-        private Object writeReplace() {
-            return new CollSer(CollSer.IMM_MAP);
-        }
-
-        @Override
-        public int hashCode() {
-            return 0;
-        }
-    }
-
     static final class Map1<K,V> extends AbstractImmutableMap<K,V> {
         @Stable
         private final K k0;
@@ -656,8 +721,12 @@
      * @param <V> the value type
      */
     static final class MapN<K,V> extends AbstractImmutableMap<K,V> {
+
+        static final Map<?,?> EMPTY_MAP = new MapN<>();
+
         @Stable
         final Object[] table; // pairs of key, value
+
         @Stable
         final int size; // number of pairs
 
@@ -689,14 +758,16 @@
 
         @Override
         public boolean containsKey(Object o) {
-            return probe(o) >= 0; // implicit nullcheck of o
+            Objects.requireNonNull(o);
+            return size > 0 && probe(o) >= 0;
         }
 
         @Override
         public boolean containsValue(Object o) {
+            Objects.requireNonNull(o);
             for (int i = 1; i < table.length; i += 2) {
                 Object v = table[i];
-                if (v != null && o.equals(v)) { // implicit nullcheck of o
+                if (v != null && o.equals(v)) {
                     return true;
                 }
             }
@@ -718,6 +789,10 @@
         @Override
         @SuppressWarnings("unchecked")
         public V get(Object o) {
+            if (size == 0) {
+                Objects.requireNonNull(o);
+                return null;
+            }
             int i = probe(o);
             if (i >= 0) {
                 return (V)table[i+1];
@@ -733,7 +808,7 @@
 
         @Override
         public Set<Map.Entry<K,V>> entrySet() {
-            return new AbstractSet<Map.Entry<K,V>>() {
+            return new AbstractSet<>() {
                 @Override
                 public int size() {
                     return MapN.this.size;
@@ -741,7 +816,7 @@
 
                 @Override
                 public Iterator<Map.Entry<K,V>> iterator() {
-                    return new Iterator<Map.Entry<K,V>>() {
+                    return new Iterator<>() {
                         int idx = 0;
 
                         @Override
@@ -948,7 +1023,7 @@
                     return Set.of(array);
                 case IMM_MAP:
                     if (array.length == 0) {
-                        return ImmutableCollections.Map0.instance();
+                        return ImmutableCollections.emptyMap();
                     } else if (array.length == 2) {
                         return new ImmutableCollections.Map1<>(array[0], array[1]);
                     } else {
--- a/src/java.base/share/classes/java/util/List.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/util/List.java	Fri Mar 23 11:14:43 2018 -0700
@@ -788,7 +788,7 @@
      * @since 9
      */
     static <E> List<E> of() {
-        return ImmutableCollections.List0.instance();
+        return ImmutableCollections.emptyList();
     }
 
     /**
@@ -804,7 +804,7 @@
      * @since 9
      */
     static <E> List<E> of(E e1) {
-        return new ImmutableCollections.List1<>(e1);
+        return new ImmutableCollections.List12<>(e1);
     }
 
     /**
@@ -821,7 +821,7 @@
      * @since 9
      */
     static <E> List<E> of(E e1, E e2) {
-        return new ImmutableCollections.List2<>(e1, e2);
+        return new ImmutableCollections.List12<>(e1, e2);
     }
 
     /**
@@ -1031,11 +1031,11 @@
     static <E> List<E> of(E... elements) {
         switch (elements.length) { // implicit null check of elements
             case 0:
-                return ImmutableCollections.List0.instance();
+                return ImmutableCollections.emptyList();
             case 1:
-                return new ImmutableCollections.List1<>(elements[0]);
+                return new ImmutableCollections.List12<>(elements[0]);
             case 2:
-                return new ImmutableCollections.List2<>(elements[0], elements[1]);
+                return new ImmutableCollections.List12<>(elements[0], elements[1]);
             default:
                 return new ImmutableCollections.ListN<>(elements);
         }
--- a/src/java.base/share/classes/java/util/Map.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/util/Map.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1287,7 +1287,7 @@
      * @since 9
      */
     static <K, V> Map<K, V> of() {
-        return ImmutableCollections.Map0.instance();
+        return ImmutableCollections.emptyMap();
     }
 
     /**
@@ -1604,11 +1604,11 @@
     @SuppressWarnings("varargs")
     static <K, V> Map<K, V> ofEntries(Entry<? extends K, ? extends V>... entries) {
         if (entries.length == 0) { // implicit null check of entries array
-            return ImmutableCollections.Map0.instance();
+            return ImmutableCollections.emptyMap();
         } else if (entries.length == 1) {
             // implicit null check of the array slot
             return new ImmutableCollections.Map1<>(entries[0].getKey(),
-                                                   entries[0].getValue());
+                    entries[0].getValue());
         } else {
             Object[] kva = new Object[entries.length << 1];
             int a = 0;
--- a/src/java.base/share/classes/java/util/Scanner.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/util/Scanner.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -2897,7 +2897,7 @@
      * letters:
      *
      * <pre>{@code
-     * try (Scanner sc = new Scanner(Paths.get("input.txt"))) {
+     * try (Scanner sc = new Scanner(Path.of("input.txt"))) {
      *     Pattern pat = Pattern.compile("[A-Z]{7,}");
      *     List<String> capWords = sc.findAll(pat)
      *                               .map(MatchResult::group)
--- a/src/java.base/share/classes/java/util/Set.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/java/util/Set.java	Fri Mar 23 11:14:43 2018 -0700
@@ -449,7 +449,7 @@
      * @since 9
      */
     static <E> Set<E> of() {
-        return ImmutableCollections.Set0.instance();
+        return ImmutableCollections.emptySet();
     }
 
     /**
@@ -464,7 +464,7 @@
      * @since 9
      */
     static <E> Set<E> of(E e1) {
-        return new ImmutableCollections.Set1<>(e1);
+        return new ImmutableCollections.Set12<>(e1);
     }
 
     /**
@@ -481,7 +481,7 @@
      * @since 9
      */
     static <E> Set<E> of(E e1, E e2) {
-        return new ImmutableCollections.Set2<>(e1, e2);
+        return new ImmutableCollections.Set12<>(e1, e2);
     }
 
     /**
@@ -692,11 +692,11 @@
     static <E> Set<E> of(E... elements) {
         switch (elements.length) { // implicit null check of elements
             case 0:
-                return ImmutableCollections.Set0.instance();
+                return ImmutableCollections.emptySet();
             case 1:
-                return new ImmutableCollections.Set1<>(elements[0]);
+                return new ImmutableCollections.Set12<>(elements[0]);
             case 2:
-                return new ImmutableCollections.Set2<>(elements[0], elements[1]);
+                return new ImmutableCollections.Set12<>(elements[0], elements[1]);
             default:
                 return new ImmutableCollections.SetN<>(elements);
         }
--- a/src/java.base/share/classes/jdk/internal/loader/BootLoader.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/jdk/internal/loader/BootLoader.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -32,7 +32,6 @@
 import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.Arrays;
@@ -243,8 +242,8 @@
                 mn = location.substring(5, location.length());
             } else if (location.startsWith("file:/")) {
                 // named module in exploded image
-                Path path = Paths.get(URI.create(location));
-                Path modulesDir = Paths.get(JAVA_HOME, "modules");
+                Path path = Path.of(URI.create(location));
+                Path modulesDir = Path.of(JAVA_HOME, "modules");
                 if (path.startsWith(modulesDir)) {
                     mn = path.getFileName().toString();
                 }
@@ -267,7 +266,7 @@
         private static URL toFileURL(String location) {
             return AccessController.doPrivileged(new PrivilegedAction<>() {
                 public URL run() {
-                    Path path = Paths.get(location);
+                    Path path = Path.of(location);
                     if (Files.isRegularFile(path)) {
                         try {
                             return path.toUri().toURL();
@@ -285,7 +284,7 @@
         private static Manifest getManifest(String location) {
             return AccessController.doPrivileged(new PrivilegedAction<>() {
                 public Manifest run() {
-                    Path jar = Paths.get(location);
+                    Path jar = Path.of(location);
                     try (InputStream in = Files.newInputStream(jar);
                          JarInputStream jis = new JarInputStream(in, false)) {
                         return jis.getManifest();
--- a/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/jdk/internal/loader/ClassLoaders.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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
@@ -28,7 +28,7 @@
 import java.io.IOException;
 import java.net.URL;
 import java.nio.file.InvalidPathException;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.security.CodeSource;
 import java.security.PermissionCollection;
 import java.util.jar.Manifest;
@@ -223,7 +223,7 @@
             // Use an intermediate File object to construct a URI/URL without
             // authority component as URLClassPath can't handle URLs with a UNC
             // server name in the authority component.
-            return Paths.get(s).toRealPath().toFile().toURI().toURL();
+            return Path.of(s).toRealPath().toFile().toURI().toURL();
         } catch (InvalidPathException | IOException ignore) {
             // malformed path string or class path element does not exist
             return null;
--- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -34,7 +34,6 @@
 import java.lang.module.ResolvedModule;
 import java.net.URI;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -539,7 +538,7 @@
             Path[] paths = new Path[dirs.length];
             int i = 0;
             for (String dir: dirs) {
-                paths[i++] = Paths.get(dir);
+                paths[i++] = Path.of(dir);
             }
             return ModulePath.of(patcher, paths);
         }
--- a/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/jdk/internal/module/ModuleHashesBuilder.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -30,7 +30,6 @@
 import java.lang.module.ResolvedModule;
 import java.net.URI;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Deque;
@@ -129,7 +128,7 @@
             () -> new InternalError("Selected module " + name + " not on module path"));
 
         URI uri = rm.reference().location().get();
-        Path path = Paths.get(uri);
+        Path path = Path.of(uri);
         String fn = path.getFileName().toString();
         if (!fn.endsWith(".jar") && !fn.endsWith(".jmod")) {
             throw new UnsupportedOperationException(path + " is not a modular JAR or jmod file");
--- a/src/java.base/share/classes/jdk/internal/module/ModulePath.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/jdk/internal/module/ModulePath.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -43,7 +43,6 @@
 import java.nio.file.Files;
 import java.nio.file.NoSuchFileException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -360,7 +359,7 @@
         URI uri = mref.location().orElse(null);
         if (uri != null) {
             if (uri.getScheme().equalsIgnoreCase("file")) {
-                Path file = Paths.get(uri);
+                Path file = Path.of(uri);
                 return file.getFileName().toString();
             } else {
                 return uri.toString();
--- a/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/jdk/internal/module/SystemModuleFinders.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 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,7 +38,6 @@
 import java.nio.ByteBuffer;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayDeque;
@@ -185,7 +184,7 @@
 
         // probe to see if this is an images build
         String home = System.getProperty("java.home");
-        Path modules = Paths.get(home, "lib", "modules");
+        Path modules = Path.of(home, "lib", "modules");
         if (Files.isRegularFile(modules)) {
             if (USE_FAST_PATH) {
                 SystemModules systemModules = allSystemModules();
@@ -205,7 +204,7 @@
         }
 
         // exploded build (do not cache module finder)
-        Path dir = Paths.get(home, "modules");
+        Path dir = Path.of(home, "modules");
         if (!Files.isDirectory(dir))
             throw new InternalError("Unable to detect the run-time image");
         ModuleFinder f = ModulePath.of(ModuleBootstrap.patcher(), dir);
--- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -508,8 +508,7 @@
                 if (remote != null) {
                     // connected
                     if (!target.equals(remote)) {
-                        throw new IllegalArgumentException(
-                            "Connected address not equal to target address");
+                        throw new AlreadyConnectedException();
                     }
                     do {
                         n = IOUtil.write(fd, src, -1, nd);
--- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java	Fri Mar 23 11:14:43 2018 -0700
@@ -397,7 +397,9 @@
      * The read end of the pipe is returned in the high 32 bits,
      * while the write end is returned in the low 32 bits.
      */
-    static native long makePipe(boolean blocking);
+    static native long makePipe(boolean blocking) throws IOException;
+
+    static native int write1(int fd, byte b) throws IOException;
 
     static native boolean drain(int fd) throws IOException;
 
--- a/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -33,10 +33,10 @@
 
 
 /**
- * An implementation of SelectionKey for Solaris.
+ * An implementation of SelectionKey.
  */
 
-public class SelectionKeyImpl
+public final class SelectionKeyImpl
     extends AbstractSelectionKey
 {
 
@@ -54,12 +54,14 @@
         selector = sel;
     }
 
+    @Override
     public SelectableChannel channel() {
         return (SelectableChannel)channel;
     }
 
+    @Override
     public Selector selector() {
-        return selector;
+        return (Selector)selector;
     }
 
     int getIndex() {                                    // package-private
@@ -75,16 +77,19 @@
             throw new CancelledKeyException();
     }
 
+    @Override
     public int interestOps() {
         ensureValid();
         return interestOps;
     }
 
+    @Override
     public SelectionKey interestOps(int ops) {
         ensureValid();
         return nioInterestOps(ops);
     }
 
+    @Override
     public int readyOps() {
         ensureValid();
         return readyOps;
@@ -131,4 +136,6 @@
         return sb.toString();
     }
 
+    // used by Selector implementations to record when the key was selected
+    int lastPolled;
 }
--- a/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/SelectorImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -78,6 +78,16 @@
         return publicSelectedKeys;
     }
 
+    /**
+     * Returns the public view of the key sets
+     */
+    protected final Set<SelectionKey> nioKeys() {
+        return publicKeys;
+    }
+    protected final Set<SelectionKey> nioSelectedKeys() {
+        return publicSelectedKeys;
+    }
+
     protected abstract int doSelect(long timeout) throws IOException;
 
     private int lockAndDoSelect(long timeout) throws IOException {
@@ -125,8 +135,6 @@
 
     protected abstract void implClose() throws IOException;
 
-    public abstract void putEventOps(SelectionKeyImpl sk, int ops);
-
     @Override
     protected final SelectionKey register(AbstractSelectableChannel ch,
                                           int ops,
@@ -166,4 +174,9 @@
             }
         }
     }
+
+    /**
+     * Invoked to change the key's interest set
+     */
+    public abstract void putEventOps(SelectionKeyImpl ski, int ops);
 }
--- a/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -210,25 +210,20 @@
 
     @Override
     public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
-        acceptLock.lock();
-        try {
-            synchronized (stateLock) {
-                ensureOpen();
-                if (localAddress != null)
-                    throw new AlreadyBoundException();
-                InetSocketAddress isa = (local == null)
-                                        ? new InetSocketAddress(0)
-                                        : Net.checkAddress(local);
-                SecurityManager sm = System.getSecurityManager();
-                if (sm != null)
-                    sm.checkListen(isa.getPort());
-                NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
-                Net.bind(fd, isa.getAddress(), isa.getPort());
-                Net.listen(fd, backlog < 1 ? 50 : backlog);
-                localAddress = Net.localAddress(fd);
-            }
-        } finally {
-            acceptLock.unlock();
+        synchronized (stateLock) {
+            ensureOpen();
+            if (localAddress != null)
+                throw new AlreadyBoundException();
+            InetSocketAddress isa = (local == null)
+                                    ? new InetSocketAddress(0)
+                                    : Net.checkAddress(local);
+            SecurityManager sm = System.getSecurityManager();
+            if (sm != null)
+                sm.checkListen(isa.getPort());
+            NetHooks.beforeTcpBind(fd, isa.getAddress(), isa.getPort());
+            Net.bind(fd, isa.getAddress(), isa.getPort());
+            Net.listen(fd, backlog < 1 ? 50 : backlog);
+            localAddress = Net.localAddress(fd);
         }
         return this;
     }
--- a/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/security/provider/PolicyFile.java	Fri Mar 23 11:14:43 2018 -0700
@@ -30,7 +30,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URI;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.util.*;
 import java.security.*;
 import java.security.cert.Certificate;
@@ -278,7 +278,7 @@
             public URL run() {
                 String sep = File.separator;
                 try {
-                    return Paths.get(System.getProperty("java.home"),
+                    return Path.of(System.getProperty("java.home"),
                                      "lib", "security",
                                      "default.policy").toUri().toURL();
                 } catch (MalformedURLException mue) {
--- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java	Fri Mar 23 11:14:43 2018 -0700
@@ -27,7 +27,7 @@
 
 import java.io.*;
 import java.nio.file.Files;
-import java.nio.file.Paths;
+import java.nio.file.Path;
 import java.security.CodeSigner;
 import java.security.CryptoPrimitive;
 import java.security.KeyStore;
@@ -2189,7 +2189,7 @@
                 inplaceBackupName = srcksfname + ".old" + (n == 1 ? "" : n);
                 File bkFile = new File(inplaceBackupName);
                 if (!bkFile.exists()) {
-                    Files.copy(Paths.get(srcksfname), bkFile.toPath());
+                    Files.copy(Path.of(srcksfname), bkFile.toPath());
                     break;
                 }
             }
--- a/src/java.base/share/native/libjava/System.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/share/native/libjava/System.c	Fri Mar 23 11:14:43 2018 -0700
@@ -244,21 +244,8 @@
     PUTPROP(props, "line.separator", sprops->line_separator);
 
     /*
-     *  user.language
-     *  user.script, user.country, user.variant (if user's environment specifies them)
-     *  file.encoding
+     * file encoding for stdout and stderr
      */
-    PUTPROP(props, "user.language", sprops->language);
-    if (sprops->script) {
-        PUTPROP(props, "user.script", sprops->script);
-    }
-    if (sprops->country) {
-        PUTPROP(props, "user.country", sprops->country);
-    }
-    if (sprops->variant) {
-        PUTPROP(props, "user.variant", sprops->variant);
-    }
-    PUTPROP(props, "file.encoding", sprops->encoding);
     if (sprops->sun_stdout_encoding != NULL) {
         PUTPROP(props, "sun.stdout.encoding", sprops->sun_stdout_encoding);
     }
@@ -314,7 +301,7 @@
 #endif
 
     /* !!! DO NOT call PUTPROP_ForPlatformNString before this line !!!
-     * !!! I18n properties have not been set up yet !!!
+     * !!! The platform native encoding for strings has not been set up yet !!!
      */
     InitializeEncoding(env, sprops->sun_jnu_encoding);
 
@@ -379,17 +366,6 @@
         PUTPROP(props, "sun.desktop", sprops->desktop);
     }
 
-    /*
-     * unset "user.language", "user.script", "user.country", and "user.variant"
-     * in order to tell whether the command line option "-DXXXX=YYYY" is
-     * specified or not.  They will be reset in fillI18nProps() below.
-     */
-    REMOVEPROP(props, "user.language");
-    REMOVEPROP(props, "user.script");
-    REMOVEPROP(props, "user.country");
-    REMOVEPROP(props, "user.variant");
-    REMOVEPROP(props, "file.encoding");
-
     ret = JVM_InitProperties(env, props);
 
     /* reconstruct i18n related properties */
--- a/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java	Fri Mar 23 11:14:43 2018 -0700
@@ -127,7 +127,7 @@
     // descriptor is registered with /dev/poll.
     private final BitSet registered = new BitSet();
 
-    DevPollArrayWrapper() {
+    DevPollArrayWrapper() throws IOException {
         int allocationSize = NUM_POLLFDS * SIZE_POLLFD;
         pollArray = new AllocatedNativeObject(allocationSize, true);
         pollArrayAddress = pollArray.address();
@@ -136,7 +136,7 @@
             eventsHigh = new HashMap<>();
     }
 
-    void initInterrupt(int fd0, int fd1) {
+    void initInterrupt(int fd0, int fd1) throws IOException {
         outgoingInterruptFD = fd1;
         incomingInterruptFD = fd0;
         register(wfd, fd0, POLLIN);
@@ -200,7 +200,7 @@
         }
     }
 
-    void release(int fd) {
+    void release(int fd) throws IOException {
         synchronized (updateLock) {
             // ignore any pending update for this file descriptor
             setUpdateEvents(fd, IGNORE);
@@ -297,7 +297,11 @@
     boolean interrupted = false;
 
     public void interrupt() {
-        interrupt(outgoingInterruptFD);
+        try {
+            IOUtil.write1(outgoingInterruptFD, (byte)0);
+        } catch (IOException ioe) {
+            throw new InternalError(ioe);
+        }
     }
 
     public int interruptedIndex() {
@@ -312,13 +316,12 @@
         interrupted = false;
     }
 
-    private native int init();
-    private native void register(int wfd, int fd, int mask);
+    private native int init() throws IOException;
+    private native void register(int wfd, int fd, int mask) throws IOException;
     private native void registerMultiple(int wfd, long address, int len)
         throws IOException;
-    private native int poll0(long pollAddress, int numfds, long timeout,
-                             int wfd);
-    private static native void interrupt(int fd);
+    private native int poll0(long pollAddress, int numfds, long timeout, int wfd)
+        throws IOException;
 
     static {
         IOUtil.load();
--- a/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -61,7 +61,7 @@
      * Package private constructor called by factory method in
      * the abstract superclass Selector.
      */
-    DevPollSelectorImpl(SelectorProvider sp) {
+    DevPollSelectorImpl(SelectorProvider sp) throws IOException {
         super(sp);
         long pipeFds = IOUtil.makePipe(false);
         fd0 = (int) (pipeFds >>> 32);
--- a/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -181,12 +181,26 @@
         }
 
         // poll for events
-        int updated = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
+        int numEntries;
+        long to = timeout;
+        boolean timedPoll = (to > 0);
+        do {
+            long startTime = timedPoll ? System.currentTimeMillis() : 0;
+            numEntries = port_getn(pfd, pollArrayAddress, POLL_MAX, timeout);
+            if (numEntries == IOStatus.INTERRUPTED && timedPoll) {
+                // timed poll interrupted so need to adjust timeout
+                to -= System.currentTimeMillis() - startTime;
+                if (to <= 0) {
+                    // timeout also expired so no retry
+                    numEntries = 0;
+                }
+            }
+        } while (numEntries == IOStatus.INTERRUPTED);
 
         // after polling we need to queue all polled file descriptors as they
         // are candidates to register for the next poll.
         synchronized (updateLock) {
-            for (int i=0; i<updated; i++) {
+            for (int i=0; i<numEntries; i++) {
                 if (getSource(i) == PORT_SOURCE_USER) {
                     interrupted = true;
                     setDescriptor(i, -1);
@@ -199,7 +213,7 @@
             }
         }
 
-        return updated;
+        return numEntries;
     }
 
     private void setInterest(int fd) {
--- a/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2013, 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
@@ -164,7 +164,10 @@
                     // A error here is fatal (thread will not be replaced)
                     replaceMe = false;
                     try {
-                        port_get(port, address);
+                        int n;
+                        do {
+                            n = port_get(port, address);
+                        } while (n == IOStatus.INTERRUPTED);
                     } catch (IOException x) {
                         x.printStackTrace();
                         return;
@@ -240,7 +243,7 @@
     /**
      * Retrieves a single event from a port
      */
-    static native void port_get(int port, long pe) throws IOException;
+    static native int port_get(int port, long address) throws IOException;
 
     /**
      * Retrieves at most {@code max} events from a port.
--- a/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/classes/sun/nio/fs/SolarisFileSystemProvider.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2016, 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
@@ -84,9 +84,9 @@
 
     @Override
     FileTypeDetector getFileTypeDetector() {
-        Path userMimeTypes = Paths.get(
+        Path userMimeTypes = Path.of(
             GetPropertyAction.privilegedGetProperty("user.home"), ".mime.types");
-        Path etcMimeTypes = Paths.get("/etc/mime.types");
+        Path etcMimeTypes = Path.of("/etc/mime.types");
 
         return chain(new MimeTypesFileTypeDetector(userMimeTypes),
                      new MimeTypesFileTypeDetector(etcMimeTypes));
--- a/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -176,14 +176,3 @@
     }
     return result;
 }
-
-JNIEXPORT void JNICALL
-Java_sun_nio_ch_DevPollArrayWrapper_interrupt(JNIEnv *env, jclass this, jint fd)
-{
-    int fakebuf[1];
-    fakebuf[0] = 1;
-    if (write(fd, fakebuf, 1) < 0) {
-        JNU_ThrowIOExceptionWithLastError(env,
-                                          "Write to interrupt fd failed");
-    }
-}
--- a/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/solaris/native/libnio/ch/SolarisEventPort.c	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2012, 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
@@ -23,17 +23,18 @@
  * questions.
  */
 
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <sys/types.h>
+#include <port.h>
+
 #include "jni.h"
 #include "jni_util.h"
 #include "jvm.h"
 #include "jlong.h"
+#include "nio.h"
 #include "nio_util.h"
 
-#include <stdlib.h>
-#include <dlfcn.h>
-#include <sys/types.h>
-#include <port.h>
-
 #include "sun_nio_ch_SolarisEventPort.h"
 
 JNIEXPORT jint JNICALL
@@ -51,8 +52,10 @@
 Java_sun_nio_ch_SolarisEventPort_port_1close
     (JNIEnv* env, jclass clazz, jint port)
 {
-    int res;
-    RESTARTABLE(close(port), res);
+    int res = close(port);
+    if (res < 0 && res != EINTR) {
+        JNU_ThrowIOExceptionWithLastError(env, "close failed");
+    }
 }
 
 JNIEXPORT jboolean JNICALL
@@ -93,17 +96,23 @@
     }
 }
 
-JNIEXPORT void JNICALL
+JNIEXPORT jint JNICALL
 Java_sun_nio_ch_SolarisEventPort_port_1get(JNIEnv* env, jclass clazz,
     jint port, jlong eventAddress)
 {
     int res;
     port_event_t* ev = (port_event_t*)jlong_to_ptr(eventAddress);
 
-    RESTARTABLE(port_get((int)port, ev, NULL), res);
+    res = port_get((int)port, ev, NULL);
     if (res == -1) {
-        JNU_ThrowIOExceptionWithLastError(env, "port_get");
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "port_get failed");
+            return IOS_THROWN;
+        }
     }
+    return res;
 }
 
 JNIEXPORT jint JNICALL
@@ -125,9 +134,13 @@
     }
 
     res = port_getn((int)port, list, (uint_t)max, &n, tsp);
-    if (res == -1) {
-        if (errno != ETIME && errno != EINTR)
-            JNU_ThrowIOExceptionWithLastError(env, "port_getn");
+    if (res == -1 && errno != ETIME) {
+        if (errno == EINTR) {
+            return IOS_INTERRUPTED;
+        } else {
+            JNU_ThrowIOExceptionWithLastError(env, "port_getn failed");
+            return IOS_THROWN;
+        }
     }
 
     return (jint)n;
--- a/src/java.base/unix/classes/sun/nio/ch/PipeImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/unix/classes/sun/nio/ch/PipeImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, 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
@@ -38,7 +38,7 @@
     private final SourceChannel source;
     private final SinkChannel sink;
 
-    PipeImpl(SelectorProvider sp) {
+    PipeImpl(SelectorProvider sp) throws IOException {
         long pipeFds = IOUtil.makePipe(true);
         int readFd = (int) (pipeFds >>> 32);
         int writeFd = (int) pipeFds;
--- a/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -51,7 +51,7 @@
      * Package private constructor called by factory method in
      * the abstract superclass Selector.
      */
-    PollSelectorImpl(SelectorProvider sp) {
+    PollSelectorImpl(SelectorProvider sp) throws IOException {
         super(sp, 1, 1);
         long pipeFds = IOUtil.makePipe(false);
         fd0 = (int) (pipeFds >>> 32);
--- a/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, 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
@@ -25,15 +25,15 @@
 
 package sun.nio.ch;
 
-import java.io.*;
+import java.io.FileDescriptor;
+import java.io.IOException;
 
 /**
  * Allows different platforms to call different native methods
  * for read and write operations.
  */
 
-class SocketDispatcher extends NativeDispatcher
-{
+class SocketDispatcher extends NativeDispatcher {
 
     int read(FileDescriptor fd, long address, int len) throws IOException {
         return FileDispatcherImpl.read0(fd, address, len);
--- a/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/unix/classes/sun/nio/fs/UnixFileStore.java	Fri Mar 23 11:14:43 2018 -0700
@@ -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
@@ -260,7 +260,7 @@
     private static Properties loadProperties() {
         Properties result = new Properties();
         String fstypes = System.getProperty("java.home") + "/lib/fstypes.properties";
-        Path file = Paths.get(fstypes);
+        Path file = Path.of(fstypes);
         try {
             try (ReadableByteChannel rbc = Files.newByteChannel(file)) {
                 result.load(Channels.newReader(rbc, "UTF-8"));
--- a/src/java.base/unix/native/libnio/ch/IOUtil.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.base/unix/native/libnio/ch/IOUtil.c	Fri Mar 23 11:14:43 2018 -0700
@@ -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
@@ -104,10 +104,19 @@
     return ((jlong) fd[0] << 32) | (jlong) fd[1];
 }
 
+
+JNIEXPORT jint JNICALL
+Java_sun_nio_ch_IOUtil_write1(JNIEnv *env, jclass cl, jint fd, jbyte b)
+{
+    char c = (char)b;
+    return convertReturnVal(env, write(fd, &c, 1), JNI_FALSE);
+}
+
+
 JNIEXPORT jboolean JNICALL
 Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd)
 {
-    char buf[128];
+    char buf[16];
     int tn = 0;
 
     for (;;) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  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.
+ */
+
+//#define USE_ERROR
+//#define USE_TRACE
+
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+
+static void alsaDebugOutput(const char *file, int line, const char *function, int err, const char *fmt, ...) {
+#ifdef USE_ERROR
+    va_list args;
+    va_start(args, fmt);
+    printf("%s:%d function %s: error %d: %s\n", file, line, function, err, snd_strerror(err));
+    if (strlen(fmt) > 0) {
+        vprintf(fmt, args);
+    }
+    va_end(args);
+#endif
+}
+
+static int alsa_inited = 0;
+static int alsa_enumerate_pcm_subdevices = FALSE; // default: no
+static int alsa_enumerate_midi_subdevices = FALSE; // default: no
+
+/*
+ * Declare library specific JNI_Onload entry if static build
+ */
+DEF_STATIC_JNI_OnLoad
+
+void initAlsaSupport() {
+    char* enumerate;
+    if (!alsa_inited) {
+        alsa_inited = TRUE;
+        snd_lib_error_set_handler(&alsaDebugOutput);
+
+        enumerate = getenv(ENV_ENUMERATE_PCM_SUBDEVICES);
+        if (enumerate != NULL && strlen(enumerate) > 0
+            && (enumerate[0] != 'f')   // false
+            && (enumerate[0] != 'F')   // False
+            && (enumerate[0] != 'n')   // no
+            && (enumerate[0] != 'N')) { // NO
+            alsa_enumerate_pcm_subdevices = TRUE;
+        }
+#ifdef ALSA_MIDI_ENUMERATE_SUBDEVICES
+        alsa_enumerate_midi_subdevices = TRUE;
+#endif
+    }
+}
+
+
+/* if true (non-zero), ALSA sub devices should be listed as separate devices
+ */
+int needEnumerateSubdevices(int isMidi) {
+    initAlsaSupport();
+    return isMidi ? alsa_enumerate_midi_subdevices
+                  : alsa_enumerate_pcm_subdevices;
+}
+
+
+/*
+ * deviceID contains packed card, device and subdevice numbers
+ * each number takes 10 bits
+ * "default" device has id == ALSA_DEFAULT_DEVICE_ID
+ */
+UINT32 encodeDeviceID(int card, int device, int subdevice) {
+    return (((card & 0x3FF) << 20) | ((device & 0x3FF) << 10)
+           | (subdevice & 0x3FF)) + 1;
+}
+
+
+void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice,
+                    int isMidi) {
+    deviceID--;
+    *card = (deviceID >> 20) & 0x3FF;
+    *device = (deviceID >> 10) & 0x3FF;
+    if (needEnumerateSubdevices(isMidi)) {
+        *subdevice = deviceID  & 0x3FF;
+    } else {
+        *subdevice = -1; // ALSA will choose any subdevices
+    }
+}
+
+
+void getDeviceString(char* buffer, int card, int device, int subdevice,
+                     int usePlugHw, int isMidi) {
+    if (needEnumerateSubdevices(isMidi)) {
+        sprintf(buffer, "%s:%d,%d,%d",
+                        usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE,
+                        card, device, subdevice);
+    } else {
+        sprintf(buffer, "%s:%d,%d",
+                        usePlugHw ? ALSA_PLUGHARDWARE : ALSA_HARDWARE,
+                        card, device);
+    }
+}
+
+
+void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID,
+                                 int usePlugHw, int isMidi) {
+    int card, device, subdevice;
+
+    if (deviceID == ALSA_DEFAULT_DEVICE_ID) {
+        strcpy(buffer, ALSA_DEFAULT_DEVICE_NAME);
+    } else {
+        decodeDeviceID(deviceID, &card, &device, &subdevice, isMidi);
+        getDeviceString(buffer, card, device, subdevice, usePlugHw, isMidi);
+    }
+}
+
+
+static int hasGottenALSAVersion = FALSE;
+#define ALSAVersionString_LENGTH 200
+static char ALSAVersionString[ALSAVersionString_LENGTH];
+
+void getALSAVersion(char* buffer, int len) {
+    if (!hasGottenALSAVersion) {
+        // get alsa version from proc interface
+        FILE* file;
+        int curr, len, totalLen, inVersionString;
+        file = fopen(ALSA_VERSION_PROC_FILE, "r");
+        ALSAVersionString[0] = 0;
+        if (file) {
+            if (NULL != fgets(ALSAVersionString, ALSAVersionString_LENGTH, file)) {
+                // parse for version number
+                totalLen = strlen(ALSAVersionString);
+                inVersionString = FALSE;
+                len = 0;
+                curr = 0;
+                while (curr < totalLen) {
+                    if (!inVersionString) {
+                        // is this char the beginning of a version string ?
+                        if (ALSAVersionString[curr] >= '0'
+                            && ALSAVersionString[curr] <= '9') {
+                            inVersionString = TRUE;
+                        }
+                    }
+                    if (inVersionString) {
+                        // the version string ends with white space
+                        if (ALSAVersionString[curr] <= 32) {
+                            break;
+                        }
+                        if (curr != len) {
+                            // copy this char to the beginning of the string
+                            ALSAVersionString[len] = ALSAVersionString[curr];
+                        }
+                        len++;
+                    }
+                    curr++;
+                }
+                // remove trailing dots
+                while ((len > 0) && (ALSAVersionString[len - 1] == '.')) {
+                    len--;
+                }
+                // null terminate
+                ALSAVersionString[len] = 0;
+            }
+            fclose(file);
+            hasGottenALSAVersion = TRUE;
+        }
+    }
+    strncpy(buffer, ALSAVersionString, len);
+}
+
+
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_CommonUtils.h	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2003, 2007, 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 <alsa/asoundlib.h>
+#include "Utilities.h"
+
+#ifndef PLATFORM_API_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
+#define PLATFORM_API_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
+
+#define ALSA_VERSION_PROC_FILE "/proc/asound/version"
+#define ALSA_HARDWARE "hw"
+#define ALSA_HARDWARE_CARD ALSA_HARDWARE":%d"
+#define ALSA_HARDWARE_DEVICE ALSA_HARDWARE_CARD",%d"
+#define ALSA_HARDWARE_SUBDEVICE ALSA_HARDWARE_DEVICE",%d"
+
+#define ALSA_PLUGHARDWARE "plughw"
+#define ALSA_DEFAULT_DEVICE_NAME "default"
+
+#define ALSA_DEFAULT_DEVICE_ID (0)
+
+#define ALSA_PCM     (0)
+#define ALSA_RAWMIDI (1)
+
+// for use in info objects
+#define ALSA_VENDOR "ALSA (http://www.alsa-project.org)"
+
+// Environment variable for inclusion of subdevices in device listing.
+// If this variable is unset or "no", then subdevices are ignored, and
+// it's ALSA's choice which one to use (enables hardware mixing)
+#define ENV_ENUMERATE_PCM_SUBDEVICES "ALSA_ENUMERATE_PCM_SUBDEVICES"
+
+// if defined, subdevices are listed.
+//#undef ALSA_MIDI_ENUMERATE_SUBDEVICES
+#define ALSA_MIDI_ENUMERATE_SUBDEVICES
+
+// must be called before any ALSA calls
+void initAlsaSupport();
+
+/* if true (non-zero), ALSA sub devices should be listed as separate devices
+ */
+int needEnumerateSubdevices(int isMidi);
+
+
+/*
+ * deviceID contains packed card, device and subdevice numbers
+ * each number takes 10 bits
+ * "default" device has id == ALSA_DEFAULT_DEVICE_ID
+ */
+UINT32 encodeDeviceID(int card, int device, int subdevice);
+
+void decodeDeviceID(UINT32 deviceID, int* card, int* device, int* subdevice,
+                    int isMidi);
+
+void getDeviceStringFromDeviceID(char* buffer, UINT32 deviceID,
+                                 int usePlugHw, int isMidi);
+
+void getALSAVersion(char* buffer, int len);
+
+
+#endif // PLATFORM_API_LINUXOS_ALSA_COMMONUTILS_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiIn.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,354 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#define USE_ERROR
+#define USE_TRACE
+
+#if USE_PLATFORM_MIDI_IN == TRUE
+
+
+#include <alsa/asoundlib.h>
+#include "PlatformMidi.h"
+#include "PLATFORM_API_LinuxOS_ALSA_MidiUtils.h"
+#if defined(i586)
+#include <sys/utsname.h>
+#endif
+
+/*
+ * Helper methods
+ */
+
+static inline UINT32 packMessage(int status, int data1, int data2) {
+    return ((status & 0xFF) | ((data1 & 0xFF) << 8) | ((data2 & 0xFF) << 16));
+}
+
+
+static void setShortMessage(MidiMessage* message,
+                            int status, int data1, int data2) {
+    message->type = SHORT_MESSAGE;
+    message->data.s.packedMsg = packMessage(status, data1, data2);
+}
+
+
+static void setRealtimeMessage(MidiMessage* message, int status) {
+    setShortMessage(message, status, 0, 0);
+}
+
+
+static void set14bitMessage(MidiMessage* message, int status, int value) {
+    TRACE3("14bit value: %d, lsb: %d, msb: %d\n", value, value & 0x7F, (value >> 7) & 0x7F);
+    value &= 0x3FFF;
+    TRACE3("14bit value (2): %d, lsb: %d, msb: %d\n", value, value & 0x7F, (value >> 7) & 0x7F);
+    setShortMessage(message, status,
+                    value & 0x7F,
+                    (value >> 7) & 0x7F);
+}
+
+
+/*
+ * implementation of the platform-dependent
+ * MIDI in functions declared in PlatformMidi.h
+ */
+
+char* MIDI_IN_GetErrorStr(INT32 err) {
+    return (char*) getErrorStr(err);
+}
+
+INT32 MIDI_IN_GetNumDevices() {
+/* Workaround for 6842956: 32bit app on 64bit linux
+ * gets assertion failure trying to open midiIn ports.
+ * Untill the issue is fixed in ALSA
+ * (https://bugtrack.alsa-project.org/alsa-bug/view.php?id=4807)
+ * report no midi in devices in the configuration.
+ */
+#if defined(i586)
+    static int jre32onlinux64 = -1;
+    if (jre32onlinux64 < 0) {
+        jre32onlinux64 = 0;
+        /* The workaround may be disabled setting "JAVASOUND_ENABLE_MIDIIN"
+         * environment variable.
+         */
+        if (getenv("JAVASOUND_ENABLE_MIDIIN") == NULL) {
+            struct utsname u;
+            jre32onlinux64 = 0;
+            if (uname(&u) == 0) {
+                if (strstr(u.machine, "64") != NULL) {
+                    TRACE0("jre32 on linux64 detected - report no midiIn devices\n");
+                    jre32onlinux64 = 1;
+                }
+            }
+        }
+    }
+    if (jre32onlinux64) {
+        return 0;
+    }
+#endif
+
+    TRACE0("MIDI_IN_GetNumDevices()\n");
+
+    return getMidiDeviceCount(SND_RAWMIDI_STREAM_INPUT);
+}
+
+
+INT32 MIDI_IN_GetDeviceName(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    int ret = getMidiDeviceName(SND_RAWMIDI_STREAM_INPUT, deviceIndex,
+                                name, nameLength);
+    return ret;
+}
+
+
+INT32 MIDI_IN_GetDeviceVendor(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    int ret = getMidiDeviceVendor(deviceIndex, name, nameLength);
+    return ret;
+}
+
+
+INT32 MIDI_IN_GetDeviceDescription(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    int ret = getMidiDeviceDescription(SND_RAWMIDI_STREAM_INPUT, deviceIndex,
+                                       name, nameLength);
+    return ret;
+}
+
+
+INT32 MIDI_IN_GetDeviceVersion(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    int ret = getMidiDeviceVersion(deviceIndex, name, nameLength);
+    return ret;
+}
+
+/*************************************************************************/
+
+INT32 MIDI_IN_OpenDevice(INT32 deviceIndex, MidiDeviceHandle** handle) {
+    INT32 ret;
+    TRACE0("> MIDI_IN_OpenDevice\n");
+    ret = openMidiDevice(SND_RAWMIDI_STREAM_INPUT, deviceIndex, handle);
+    TRACE1("< MIDI_IN_OpenDevice: returning %d\n", (int) ret);
+    return ret;
+}
+
+
+INT32 MIDI_IN_CloseDevice(MidiDeviceHandle* handle) {
+    INT32 ret;
+    TRACE0("> MIDI_IN_CloseDevice\n");
+    ret = closeMidiDevice(handle);
+    TRACE1("< MIDI_IN_CloseDevice: returning %d\n", (int) ret);
+    return ret;
+}
+
+
+INT32 MIDI_IN_StartDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_IN_StartDevice\n");
+    return MIDI_SUCCESS;
+}
+
+
+INT32 MIDI_IN_StopDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_IN_StopDevice\n");
+    return MIDI_SUCCESS;
+}
+
+
+INT64 MIDI_IN_GetTimeStamp(MidiDeviceHandle* handle) {
+    return getMidiTimestamp(handle);
+}
+
+
+/* read the next message from the queue */
+MidiMessage* MIDI_IN_GetMessage(MidiDeviceHandle* handle) {
+    snd_seq_event_t alsa_message;
+    MidiMessage* jdk_message;
+    int err;
+    char buffer[1];
+    int status;
+
+    TRACE0("> MIDI_IN_GetMessage\n");
+    if (!handle) {
+        ERROR0("< ERROR: MIDI_IN_GetMessage(): handle is NULL\n");
+        return NULL;
+    }
+    if (!handle->deviceHandle) {
+        ERROR0("< ERROR: MIDI_IN_GetMessage(): native handle is NULL\n");
+        return NULL;
+    }
+    if (!handle->platformData) {
+        ERROR0("< ERROR: MIDI_IN_GetMessage(): platformData is NULL\n");
+        return NULL;
+    }
+
+    /* For MIDI In, the device is left in non blocking mode. So if there is
+       no data from the device, snd_rawmidi_read() returns with -11 (EAGAIN).
+       This results in jumping back to the Java layer. */
+    while (TRUE) {
+        TRACE0("before snd_rawmidi_read()\n");
+        err = snd_rawmidi_read((snd_rawmidi_t*) handle->deviceHandle, buffer, 1);
+        TRACE0("after snd_rawmidi_read()\n");
+        if (err != 1) {
+            ERROR2("< ERROR: MIDI_IN_GetMessage(): snd_rawmidi_read() returned %d : %s\n", err, snd_strerror(err));
+            return NULL;
+        }
+        // printf("received byte: %d\n", buffer[0]);
+        err = snd_midi_event_encode_byte((snd_midi_event_t*) handle->platformData,
+                                         (int) buffer[0],
+                                         &alsa_message);
+        if (err == 1) {
+            break;
+        } else if (err < 0) {
+            ERROR1("< ERROR: MIDI_IN_GetMessage(): snd_midi_event_encode_byte() returned %d\n", err);
+            return NULL;
+        }
+    }
+    jdk_message = (MidiMessage*) calloc(sizeof(MidiMessage), 1);
+    if (!jdk_message) {
+        ERROR0("< ERROR: MIDI_IN_GetMessage(): out of memory\n");
+        return NULL;
+    }
+    // TODO: tra
+    switch (alsa_message.type) {
+    case SND_SEQ_EVENT_NOTEON:
+    case SND_SEQ_EVENT_NOTEOFF:
+    case SND_SEQ_EVENT_KEYPRESS:
+        status = (alsa_message.type == SND_SEQ_EVENT_KEYPRESS) ? 0xA0 :
+            (alsa_message.type == SND_SEQ_EVENT_NOTEON) ? 0x90 : 0x80;
+        status |= alsa_message.data.note.channel;
+        setShortMessage(jdk_message, status,
+                        alsa_message.data.note.note,
+                        alsa_message.data.note.velocity);
+        break;
+
+    case SND_SEQ_EVENT_CONTROLLER:
+        status = 0xB0 | alsa_message.data.control.channel;
+        setShortMessage(jdk_message, status,
+                        alsa_message.data.control.param,
+                        alsa_message.data.control.value);
+        break;
+
+    case SND_SEQ_EVENT_PGMCHANGE:
+    case SND_SEQ_EVENT_CHANPRESS:
+        status = (alsa_message.type == SND_SEQ_EVENT_PGMCHANGE) ? 0xC0 : 0xD0;
+        status |= alsa_message.data.control.channel;
+        setShortMessage(jdk_message, status,
+                        alsa_message.data.control.value, 0);
+        break;
+
+    case SND_SEQ_EVENT_PITCHBEND:
+        status = 0xE0 | alsa_message.data.control.channel;
+        // $$mp 2003-09-23:
+        // possible hack to work around a bug in ALSA. Necessary for
+        // ALSA 0.9.2. May be fixed in newer versions of ALSA.
+        // alsa_message.data.control.value ^= 0x2000;
+        // TRACE1("pitchbend value: %d\n", alsa_message.data.control.value);
+        set14bitMessage(jdk_message, status,
+                        alsa_message.data.control.value);
+        break;
+
+        /* System exclusive messages */
+
+    case SND_SEQ_EVENT_SYSEX:
+        jdk_message->type = LONG_MESSAGE;
+        jdk_message->data.l.size = alsa_message.data.ext.len;
+        jdk_message->data.l.data = malloc(alsa_message.data.ext.len);
+        if (jdk_message->data.l.data == NULL) {
+            ERROR0("< ERROR: MIDI_IN_GetMessage(): out of memory\n");
+            free(jdk_message);
+            jdk_message = NULL;
+        } else {
+            memcpy(jdk_message->data.l.data, alsa_message.data.ext.ptr, alsa_message.data.ext.len);
+        }
+        break;
+
+        /* System common messages */
+
+    case SND_SEQ_EVENT_QFRAME:
+        setShortMessage(jdk_message, 0xF1,
+                        alsa_message.data.control.value & 0x7F, 0);
+        break;
+
+    case SND_SEQ_EVENT_SONGPOS:
+        set14bitMessage(jdk_message, 0xF2,
+                        alsa_message.data.control.value);
+        break;
+
+    case SND_SEQ_EVENT_SONGSEL:
+        setShortMessage(jdk_message, 0xF3,
+                        alsa_message.data.control.value & 0x7F, 0);
+        break;
+
+    case SND_SEQ_EVENT_TUNE_REQUEST:
+        setRealtimeMessage(jdk_message, 0xF6);
+        break;
+
+        /* System realtime messages */
+
+    case SND_SEQ_EVENT_CLOCK:
+        setRealtimeMessage(jdk_message, 0xF8);
+        break;
+
+    case SND_SEQ_EVENT_START:
+        setRealtimeMessage(jdk_message, 0xFA);
+        break;
+
+    case SND_SEQ_EVENT_CONTINUE:
+        setRealtimeMessage(jdk_message, 0xFB);
+        break;
+
+    case SND_SEQ_EVENT_STOP:
+        setRealtimeMessage(jdk_message, 0xFC);
+        break;
+
+    case SND_SEQ_EVENT_SENSING:
+        setRealtimeMessage(jdk_message, 0xFE);
+        break;
+
+    case SND_SEQ_EVENT_RESET:
+        setRealtimeMessage(jdk_message, 0xFF);
+        break;
+
+    default:
+        ERROR0("< ERROR: MIDI_IN_GetMessage(): unhandled ALSA MIDI message type\n");
+        free(jdk_message);
+        jdk_message = NULL;
+
+    }
+
+    // set timestamp
+    if (jdk_message != NULL) {
+        jdk_message->timestamp = getMidiTimestamp(handle);
+    }
+    TRACE1("< MIDI_IN_GetMessage: returning %p\n", jdk_message);
+    return jdk_message;
+}
+
+
+void MIDI_IN_ReleaseMessage(MidiDeviceHandle* handle, MidiMessage* msg) {
+    if (!msg) {
+        ERROR0("< ERROR: MIDI_IN_ReleaseMessage(): message is NULL\n");
+        return;
+    }
+    if (msg->type == LONG_MESSAGE && msg->data.l.data) {
+        free(msg->data.l.data);
+    }
+    free(msg);
+}
+
+#endif /* USE_PLATFORM_MIDI_IN */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiOut.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2003, 2007, 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.
+ */
+
+#define USE_ERROR
+#define USE_TRACE
+
+#if USE_PLATFORM_MIDI_OUT == TRUE
+
+#include <alsa/asoundlib.h>
+#include "PlatformMidi.h"
+#include "PLATFORM_API_LinuxOS_ALSA_MidiUtils.h"
+
+
+
+static int CHANNEL_MESSAGE_LENGTH[] = {
+    -1, -1, -1, -1, -1, -1, -1, -1, 3, 3, 3, 3, 2, 2, 3 };
+/*                                 8x 9x Ax Bx Cx Dx Ex */
+
+static int SYSTEM_MESSAGE_LENGTH[] = {
+    -1, 2, 3, 2, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, 1 };
+/*  F0 F1 F2 F3  F4  F5 F6 F7 F8  F9 FA FB FC  FD FE FF */
+
+
+// the returned length includes the status byte.
+// for illegal messages, -1 is returned.
+static int getShortMessageLength(int status) {
+        int     dataLength = 0;
+        if (status < 0xF0) { // channel voice message
+                dataLength = CHANNEL_MESSAGE_LENGTH[(status >> 4) & 0xF];
+        } else {
+                dataLength = SYSTEM_MESSAGE_LENGTH[status & 0xF];
+        }
+        return dataLength;
+}
+
+
+/*
+ * implementation of the platform-dependent
+ * MIDI out functions declared in PlatformMidi.h
+ */
+char* MIDI_OUT_GetErrorStr(INT32 err) {
+    return (char*) getErrorStr(err);
+}
+
+
+INT32 MIDI_OUT_GetNumDevices() {
+    TRACE0("MIDI_OUT_GetNumDevices()\n");
+    return getMidiDeviceCount(SND_RAWMIDI_STREAM_OUTPUT);
+}
+
+
+INT32 MIDI_OUT_GetDeviceName(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    TRACE0("MIDI_OUT_GetDeviceName()\n");
+    return getMidiDeviceName(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex,
+                             name, nameLength);
+}
+
+
+INT32 MIDI_OUT_GetDeviceVendor(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    TRACE0("MIDI_OUT_GetDeviceVendor()\n");
+    return getMidiDeviceVendor(deviceIndex, name, nameLength);
+}
+
+
+INT32 MIDI_OUT_GetDeviceDescription(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    TRACE0("MIDI_OUT_GetDeviceDescription()\n");
+    return getMidiDeviceDescription(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex,
+                                    name, nameLength);
+}
+
+
+INT32 MIDI_OUT_GetDeviceVersion(INT32 deviceIndex, char *name, UINT32 nameLength) {
+    TRACE0("MIDI_OUT_GetDeviceVersion()\n");
+    return getMidiDeviceVersion(deviceIndex, name, nameLength);
+}
+
+
+/* *************************** MidiOutDevice implementation *************** */
+
+INT32 MIDI_OUT_OpenDevice(INT32 deviceIndex, MidiDeviceHandle** handle) {
+    TRACE1("MIDI_OUT_OpenDevice(): deviceIndex: %d\n", (int) deviceIndex);
+    return openMidiDevice(SND_RAWMIDI_STREAM_OUTPUT, deviceIndex, handle);
+}
+
+
+INT32 MIDI_OUT_CloseDevice(MidiDeviceHandle* handle) {
+    TRACE0("MIDI_OUT_CloseDevice()\n");
+    return closeMidiDevice(handle);
+}
+
+
+INT64 MIDI_OUT_GetTimeStamp(MidiDeviceHandle* handle) {
+    return getMidiTimestamp(handle);
+}
+
+
+INT32 MIDI_OUT_SendShortMessage(MidiDeviceHandle* handle, UINT32 packedMsg,
+                                UINT32 timestamp) {
+    int err;
+    int status;
+    int data1;
+    int data2;
+    char buffer[3];
+
+    TRACE2("> MIDI_OUT_SendShortMessage() %x, time: %u\n", packedMsg, (unsigned int) timestamp);
+    if (!handle) {
+        ERROR0("< ERROR: MIDI_OUT_SendShortMessage(): handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    if (!handle->deviceHandle) {
+        ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): native handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    status = (packedMsg & 0xFF);
+    buffer[0] = (char) status;
+    buffer[1]  = (char) ((packedMsg >> 8) & 0xFF);
+    buffer[2]  = (char) ((packedMsg >> 16) & 0xFF);
+    TRACE4("status: %d, data1: %d, data2: %d, length: %d\n", (int) buffer[0], (int) buffer[1], (int) buffer[2], getShortMessageLength(status));
+    err = snd_rawmidi_write((snd_rawmidi_t*) handle->deviceHandle, buffer, getShortMessageLength(status));
+    if (err < 0) {
+        ERROR1("  ERROR: MIDI_OUT_SendShortMessage(): snd_rawmidi_write() returned %d\n", err);
+    }
+
+    TRACE0("< MIDI_OUT_SendShortMessage()\n");
+    return err;
+}
+
+
+INT32 MIDI_OUT_SendLongMessage(MidiDeviceHandle* handle, UBYTE* data,
+                               UINT32 size, UINT32 timestamp) {
+    int err;
+
+    TRACE2("> MIDI_OUT_SendLongMessage() size %u, time: %u\n", (unsigned int) size, (unsigned int) timestamp);
+    if (!handle) {
+        ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    if (!handle->deviceHandle) {
+        ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): native handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    if (!data) {
+        ERROR0("< ERROR: MIDI_OUT_SendLongMessage(): data is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    err = snd_rawmidi_write((snd_rawmidi_t*) handle->deviceHandle,
+                            data, size);
+    if (err < 0) {
+        ERROR1("  ERROR: MIDI_OUT_SendLongMessage(): snd_rawmidi_write() returned %d\n", err);
+    }
+
+    TRACE0("< MIDI_OUT_SendLongMessage()\n");
+    return err;
+}
+
+
+#endif /* USE_PLATFORM_MIDI_OUT */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,481 @@
+/*
+ * Copyright (c) 2003, 2014, 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.
+ */
+
+#define USE_ERROR
+#define USE_TRACE
+
+#include "PLATFORM_API_LinuxOS_ALSA_MidiUtils.h"
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+#include <string.h>
+#include <sys/time.h>
+
+static INT64 getTimeInMicroseconds() {
+    struct timeval tv;
+
+    gettimeofday(&tv, NULL);
+    return (tv.tv_sec * 1000000UL) + tv.tv_usec;
+}
+
+
+const char* getErrorStr(INT32 err) {
+        return snd_strerror((int) err);
+}
+
+
+
+// callback for iteration through devices
+// returns TRUE if iteration should continue
+typedef int (*DeviceIteratorPtr)(UINT32 deviceID,
+                                 snd_rawmidi_info_t* rawmidi_info,
+                                 snd_ctl_card_info_t* cardinfo,
+                                 void *userData);
+
+// for each ALSA device, call iterator. userData is passed to the iterator
+// returns total number of iterations
+static int iterateRawmidiDevices(snd_rawmidi_stream_t direction,
+                                 DeviceIteratorPtr iterator,
+                                 void* userData) {
+    int count = 0;
+    int subdeviceCount;
+    int card, dev, subDev;
+    char devname[16];
+    int err;
+    snd_ctl_t *handle;
+    snd_rawmidi_t *rawmidi;
+    snd_rawmidi_info_t *rawmidi_info;
+    snd_ctl_card_info_t *card_info, *defcardinfo = NULL;
+    UINT32 deviceID;
+    int doContinue = TRUE;
+
+    snd_rawmidi_info_malloc(&rawmidi_info);
+    snd_ctl_card_info_malloc(&card_info);
+
+    // 1st try "default" device
+    if (direction == SND_RAWMIDI_STREAM_INPUT) {
+        err = snd_rawmidi_open(&rawmidi, NULL, ALSA_DEFAULT_DEVICE_NAME,
+                               SND_RAWMIDI_NONBLOCK);
+    } else if (direction == SND_RAWMIDI_STREAM_OUTPUT) {
+        err = snd_rawmidi_open(NULL, &rawmidi, ALSA_DEFAULT_DEVICE_NAME,
+                               SND_RAWMIDI_NONBLOCK);
+    } else {
+        ERROR0("ERROR: iterateRawmidiDevices(): direction is neither"
+               " SND_RAWMIDI_STREAM_INPUT nor SND_RAWMIDI_STREAM_OUTPUT\n");
+        err = MIDI_INVALID_ARGUMENT;
+    }
+    if (err < 0) {
+        ERROR1("ERROR: snd_rawmidi_open (\"default\"): %s\n",
+               snd_strerror(err));
+    } else {
+        err = snd_rawmidi_info(rawmidi, rawmidi_info);
+
+        snd_rawmidi_close(rawmidi);
+        if (err < 0) {
+            ERROR1("ERROR: snd_rawmidi_info (\"default\"): %s\n",
+                    snd_strerror(err));
+        } else {
+            // try to get card info
+            card = snd_rawmidi_info_get_card(rawmidi_info);
+            if (card >= 0) {
+                sprintf(devname, ALSA_HARDWARE_CARD, card);
+                if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) {
+                    if (snd_ctl_card_info(handle, card_info) >= 0) {
+                        defcardinfo = card_info;
+                    }
+                    snd_ctl_close(handle);
+                }
+            }
+            // call calback function for the device
+            if (iterator != NULL) {
+                doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, rawmidi_info,
+                                         defcardinfo, userData);
+            }
+            count++;
+        }
+    }
+
+    // iterate cards
+    card = -1;
+    TRACE0("testing for cards...\n");
+    if (snd_card_next(&card) >= 0) {
+        TRACE1("Found card %d\n", card);
+        while (doContinue && (card >= 0)) {
+            sprintf(devname, ALSA_HARDWARE_CARD, card);
+            TRACE1("Opening control for alsa rawmidi device \"%s\"...\n", devname);
+            err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK);
+            if (err < 0) {
+                ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
+            } else {
+                TRACE0("snd_ctl_open() SUCCESS\n");
+                err = snd_ctl_card_info(handle, card_info);
+                if (err < 0) {
+                    ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", card, snd_strerror(err));
+                } else {
+                    TRACE0("snd_ctl_card_info() SUCCESS\n");
+                    dev = -1;
+                    while (doContinue) {
+                        if (snd_ctl_rawmidi_next_device(handle, &dev) < 0) {
+                            ERROR0("snd_ctl_rawmidi_next_device\n");
+                        }
+                        TRACE0("snd_ctl_rawmidi_next_device() SUCCESS\n");
+                        if (dev < 0) {
+                            break;
+                        }
+                        snd_rawmidi_info_set_device(rawmidi_info, dev);
+                        snd_rawmidi_info_set_subdevice(rawmidi_info, 0);
+                        snd_rawmidi_info_set_stream(rawmidi_info, direction);
+                        err = snd_ctl_rawmidi_info(handle, rawmidi_info);
+                        TRACE0("after snd_ctl_rawmidi_info()\n");
+                        if (err < 0) {
+                            if (err != -ENOENT) {
+                                ERROR2("ERROR: snd_ctl_rawmidi_info, card=%d: %s", card, snd_strerror(err));
+                            }
+                        } else {
+                            TRACE0("snd_ctl_rawmidi_info() SUCCESS\n");
+                            subdeviceCount = needEnumerateSubdevices(ALSA_RAWMIDI)
+                                ? snd_rawmidi_info_get_subdevices_count(rawmidi_info)
+                                : 1;
+                            if (iterator!=NULL) {
+                                for (subDev = 0; subDev < subdeviceCount; subDev++) {
+                                    TRACE3("  Iterating %d,%d,%d\n", card, dev, subDev);
+                                    deviceID = encodeDeviceID(card, dev, subDev);
+                                    doContinue = (*iterator)(deviceID, rawmidi_info,
+                                                             card_info, userData);
+                                    count++;
+                                    TRACE0("returned from iterator\n");
+                                    if (!doContinue) {
+                                        break;
+                                    }
+                                }
+                            } else {
+                                count += subdeviceCount;
+                            }
+                        }
+                    } // of while(doContinue)
+                }
+                snd_ctl_close(handle);
+            }
+            if (snd_card_next(&card) < 0) {
+                break;
+            }
+        }
+    } else {
+        ERROR0("No cards found!\n");
+    }
+    snd_ctl_card_info_free(card_info);
+    snd_rawmidi_info_free(rawmidi_info);
+    return count;
+}
+
+
+
+int getMidiDeviceCount(snd_rawmidi_stream_t direction) {
+    int deviceCount;
+    TRACE0("> getMidiDeviceCount()\n");
+    initAlsaSupport();
+    deviceCount = iterateRawmidiDevices(direction, NULL, NULL);
+    TRACE0("< getMidiDeviceCount()\n");
+    return deviceCount;
+}
+
+
+
+/*
+  userData is assumed to be a pointer to ALSA_MIDIDeviceDescription.
+  ALSA_MIDIDeviceDescription->index has to be set to the index of the device
+  we want to get information of before this method is called the first time via
+  iterateRawmidiDevices(). On each call of this method,
+  ALSA_MIDIDeviceDescription->index is decremented. If it is equal to zero,
+  we have reached the desired device, so action is taken.
+  So after successful completion of iterateRawmidiDevices(),
+  ALSA_MIDIDeviceDescription->index is zero. If it isn't, this is an
+  indication of an error.
+*/
+static int deviceInfoIterator(UINT32 deviceID, snd_rawmidi_info_t *rawmidi_info,
+                              snd_ctl_card_info_t *cardinfo, void *userData) {
+    char buffer[300];
+    ALSA_MIDIDeviceDescription* desc = (ALSA_MIDIDeviceDescription*)userData;
+#ifdef ALSA_MIDI_USE_PLUGHW
+    int usePlugHw = 1;
+#else
+    int usePlugHw = 0;
+#endif
+
+    TRACE0("deviceInfoIterator\n");
+    initAlsaSupport();
+    if (desc->index == 0) {
+        // we found the device with correct index
+        desc->deviceID = deviceID;
+
+        buffer[0]=' '; buffer[1]='[';
+        // buffer[300] is enough to store the actual device string w/o overrun
+        getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_RAWMIDI);
+        strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1);
+        strncpy(desc->name,
+                (cardinfo != NULL)
+                    ? snd_ctl_card_info_get_id(cardinfo)
+                    : snd_rawmidi_info_get_id(rawmidi_info),
+                desc->strLen - strlen(buffer));
+        strncat(desc->name, buffer, desc->strLen - strlen(desc->name));
+        desc->description[0] = 0;
+        if (cardinfo != NULL) {
+            strncpy(desc->description, snd_ctl_card_info_get_name(cardinfo),
+                    desc->strLen);
+            strncat(desc->description, ", ",
+                    desc->strLen - strlen(desc->description));
+        }
+        strncat(desc->description, snd_rawmidi_info_get_id(rawmidi_info),
+                desc->strLen - strlen(desc->description));
+        strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
+        strncat(desc->description, snd_rawmidi_info_get_name(rawmidi_info),
+                desc->strLen - strlen(desc->description));
+        TRACE2("Returning %s, %s\n", desc->name, desc->description);
+        return FALSE; // do not continue iteration
+    }
+    desc->index--;
+    return TRUE;
+}
+
+
+static int getMIDIDeviceDescriptionByIndex(snd_rawmidi_stream_t direction,
+                                           ALSA_MIDIDeviceDescription* desc) {
+    initAlsaSupport();
+    TRACE1(" getMIDIDeviceDescriptionByIndex (index = %d)\n", desc->index);
+    iterateRawmidiDevices(direction, &deviceInfoIterator, desc);
+    return (desc->index == 0) ? MIDI_SUCCESS : MIDI_INVALID_DEVICEID;
+}
+
+
+
+int initMIDIDeviceDescription(ALSA_MIDIDeviceDescription* desc, int index) {
+    int ret = MIDI_SUCCESS;
+    desc->index = index;
+    desc->strLen = 200;
+    desc->name = (char*) calloc(desc->strLen + 1, 1);
+    desc->description = (char*) calloc(desc->strLen + 1, 1);
+    if (! desc->name ||
+        ! desc->description) {
+        ret = MIDI_OUT_OF_MEMORY;
+    }
+    return ret;
+}
+
+
+void freeMIDIDeviceDescription(ALSA_MIDIDeviceDescription* desc) {
+    if (desc->name) {
+        free(desc->name);
+    }
+    if (desc->description) {
+        free(desc->description);
+    }
+}
+
+
+int getMidiDeviceName(snd_rawmidi_stream_t direction, int index, char *name,
+                      UINT32 nameLength) {
+    ALSA_MIDIDeviceDescription desc;
+    int ret;
+
+    TRACE1("getMidiDeviceName: nameLength: %d\n", (int) nameLength);
+    ret = initMIDIDeviceDescription(&desc, index);
+    if (ret == MIDI_SUCCESS) {
+        TRACE0("getMidiDeviceName: initMIDIDeviceDescription() SUCCESS\n");
+        ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
+        if (ret == MIDI_SUCCESS) {
+            TRACE1("getMidiDeviceName: desc.name: %s\n", desc.name);
+            strncpy(name, desc.name, nameLength - 1);
+            name[nameLength - 1] = 0;
+        }
+    }
+    freeMIDIDeviceDescription(&desc);
+    return ret;
+}
+
+
+int getMidiDeviceVendor(int index, char *name, UINT32 nameLength) {
+    strncpy(name, ALSA_VENDOR, nameLength - 1);
+    name[nameLength - 1] = 0;
+    return MIDI_SUCCESS;
+}
+
+
+int getMidiDeviceDescription(snd_rawmidi_stream_t direction,
+                             int index, char *name, UINT32 nameLength) {
+    ALSA_MIDIDeviceDescription desc;
+    int ret;
+
+    ret = initMIDIDeviceDescription(&desc, index);
+    if (ret == MIDI_SUCCESS) {
+        ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
+        if (ret == MIDI_SUCCESS) {
+            strncpy(name, desc.description, nameLength - 1);
+            name[nameLength - 1] = 0;
+        }
+    }
+    freeMIDIDeviceDescription(&desc);
+    return ret;
+}
+
+
+int getMidiDeviceVersion(int index, char *name, UINT32 nameLength) {
+    getALSAVersion(name, nameLength);
+    return MIDI_SUCCESS;
+}
+
+
+static int getMidiDeviceID(snd_rawmidi_stream_t direction, int index,
+                           UINT32* deviceID) {
+    ALSA_MIDIDeviceDescription desc;
+    int ret;
+
+    ret = initMIDIDeviceDescription(&desc, index);
+    if (ret == MIDI_SUCCESS) {
+        ret = getMIDIDeviceDescriptionByIndex(direction, &desc);
+        if (ret == MIDI_SUCCESS) {
+            // TRACE1("getMidiDeviceName: desc.name: %s\n", desc.name);
+            *deviceID = desc.deviceID;
+        }
+    }
+    freeMIDIDeviceDescription(&desc);
+    return ret;
+}
+
+
+/*
+  direction has to be either SND_RAWMIDI_STREAM_INPUT or
+  SND_RAWMIDI_STREAM_OUTPUT.
+  Returns 0 on success. Otherwise, MIDI_OUT_OF_MEMORY, MIDI_INVALID_ARGUMENT
+   or a negative ALSA error code is returned.
+*/
+INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex,
+                     MidiDeviceHandle** handle) {
+    snd_rawmidi_t* native_handle;
+    snd_midi_event_t* event_parser = NULL;
+    int err;
+    UINT32 deviceID = 0;
+    char devicename[100];
+#ifdef ALSA_MIDI_USE_PLUGHW
+    int usePlugHw = 1;
+#else
+    int usePlugHw = 0;
+#endif
+
+    TRACE0("> openMidiDevice()\n");
+
+    (*handle) = (MidiDeviceHandle*) calloc(sizeof(MidiDeviceHandle), 1);
+    if (!(*handle)) {
+        ERROR0("ERROR: openDevice: out of memory\n");
+        return MIDI_OUT_OF_MEMORY;
+    }
+
+    // TODO: iterate to get dev ID from index
+    err = getMidiDeviceID(direction, deviceIndex, &deviceID);
+    TRACE1("  openMidiDevice(): deviceID: %d\n", (int) deviceID);
+    getDeviceStringFromDeviceID(devicename, deviceID,
+                                usePlugHw, ALSA_RAWMIDI);
+    TRACE1("  openMidiDevice(): deviceString: %s\n", devicename);
+
+    // finally open the device
+    if (direction == SND_RAWMIDI_STREAM_INPUT) {
+        err = snd_rawmidi_open(&native_handle, NULL, devicename,
+                               SND_RAWMIDI_NONBLOCK);
+    } else if (direction == SND_RAWMIDI_STREAM_OUTPUT) {
+        err = snd_rawmidi_open(NULL, &native_handle, devicename,
+                               SND_RAWMIDI_NONBLOCK);
+    } else {
+        ERROR0("  ERROR: openMidiDevice(): direction is neither SND_RAWMIDI_STREAM_INPUT nor SND_RAWMIDI_STREAM_OUTPUT\n");
+        err = MIDI_INVALID_ARGUMENT;
+    }
+    if (err < 0) {
+        ERROR1("<  ERROR: openMidiDevice(): snd_rawmidi_open() returned %d\n", err);
+        free(*handle);
+        (*handle) = NULL;
+        return err;
+    }
+    /* We opened with non-blocking behaviour to not get hung if the device
+       is used by a different process. Writing, however, should
+       be blocking. So we change it here. */
+    if (direction == SND_RAWMIDI_STREAM_OUTPUT) {
+        err = snd_rawmidi_nonblock(native_handle, 0);
+        if (err < 0) {
+            ERROR1("  ERROR: openMidiDevice(): snd_rawmidi_nonblock() returned %d\n", err);
+            snd_rawmidi_close(native_handle);
+            free(*handle);
+            (*handle) = NULL;
+            return err;
+        }
+    }
+    if (direction == SND_RAWMIDI_STREAM_INPUT) {
+        err = snd_midi_event_new(EVENT_PARSER_BUFSIZE, &event_parser);
+        if (err < 0) {
+            ERROR1("  ERROR: openMidiDevice(): snd_midi_event_new() returned %d\n", err);
+            snd_rawmidi_close(native_handle);
+            free(*handle);
+            (*handle) = NULL;
+            return err;
+        }
+    }
+
+    (*handle)->deviceHandle = (void*) native_handle;
+    (*handle)->startTime = getTimeInMicroseconds();
+    (*handle)->platformData = event_parser;
+    TRACE0("< openMidiDevice(): succeeded\n");
+    return err;
+}
+
+
+
+INT32 closeMidiDevice(MidiDeviceHandle* handle) {
+    int err;
+
+    TRACE0("> closeMidiDevice()\n");
+    if (!handle) {
+        ERROR0("< ERROR: closeMidiDevice(): handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    if (!handle->deviceHandle) {
+        ERROR0("< ERROR: closeMidiDevice(): native handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    err = snd_rawmidi_close((snd_rawmidi_t*) handle->deviceHandle);
+    TRACE1("  snd_rawmidi_close() returns %d\n", err);
+    if (handle->platformData) {
+        snd_midi_event_free((snd_midi_event_t*) handle->platformData);
+    }
+    free(handle);
+    TRACE0("< closeMidiDevice: succeeded\n");
+    return err;
+}
+
+
+INT64 getMidiTimestamp(MidiDeviceHandle* handle) {
+    if (!handle) {
+        ERROR0("< ERROR: closeMidiDevice(): handle is NULL\n");
+        return MIDI_INVALID_HANDLE;
+    }
+    return getTimeInMicroseconds() - handle->startTime;
+}
+
+
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_MidiUtils.h	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2003, 2007, 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 <alsa/asoundlib.h>
+#include "Utilities.h"
+#include "PlatformMidi.h"
+
+
+#ifndef PLATFORM_API_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
+#define PLATFORM_API_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
+
+#define EVENT_PARSER_BUFSIZE (2048)
+
+// if this is defined, use plughw: devices
+//#define ALSA_MIDI_USE_PLUGHW
+#undef ALSA_MIDI_USE_PLUGHW
+
+typedef struct tag_ALSA_MIDIDeviceDescription {
+        int index;          // in
+        int strLen;         // in
+        INT32 deviceID;    // out
+        char* name;         // out
+        char* description;  // out
+} ALSA_MIDIDeviceDescription;
+
+
+const char* getErrorStr(INT32 err);
+
+/* Returns the number of devices. */
+/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
+   SND_RAWMIDI_STREAM_INPUT. */
+int getMidiDeviceCount(snd_rawmidi_stream_t direction);
+
+/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
+/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
+   SND_RAWMIDI_STREAM_INPUT. */
+int getMidiDeviceName(snd_rawmidi_stream_t direction, int index,
+                      char *name, UINT32 nameLength);
+
+/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
+int getMidiDeviceVendor(int index, char *name, UINT32 nameLength);
+
+/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
+/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
+   SND_RAWMIDI_STREAM_INPUT. */
+int getMidiDeviceDescription(snd_rawmidi_stream_t direction, int index,
+                             char *name, UINT32 nameLength);
+
+/* Returns MIDI_SUCCESS or MIDI_INVALID_DEVICEID */
+int getMidiDeviceVersion(int index, char *name, UINT32 nameLength);
+
+// returns 0 on success, otherwise MIDI_OUT_OF_MEMORY or ALSA error code
+/* direction is either SND_RAWMIDI_STREAM_OUTPUT or
+   SND_RAWMIDI_STREAM_INPUT. */
+INT32 openMidiDevice(snd_rawmidi_stream_t direction, INT32 deviceIndex,
+                     MidiDeviceHandle** handle);
+
+// returns 0 on success, otherwise a (negative) ALSA error code
+INT32 closeMidiDevice(MidiDeviceHandle* handle);
+
+INT64 getMidiTimestamp(MidiDeviceHandle* handle);
+
+#endif // PLATFORM_API_LINUXOS_ALSA_MIDIUTILS_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCM.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,941 @@
+/*
+ * Copyright (c) 2002, 2011, 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.
+ */
+
+#define USE_ERROR
+#define USE_TRACE
+
+#include "PLATFORM_API_LinuxOS_ALSA_PCMUtils.h"
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+#include "DirectAudio.h"
+
+#if USE_DAUDIO == TRUE
+
+// GetPosition method 1: based on how many bytes are passed to the kernel driver
+//                       + does not need much processor resources
+//                       - not very exact, "jumps"
+// GetPosition method 2: ask kernel about actual position of playback.
+//                       - very exact
+//                       - switch to kernel layer for each call
+// GetPosition method 3: use snd_pcm_avail() call - not yet in official ALSA
+// quick tests on a Pentium 200MMX showed max. 1.5% processor usage
+// for playing back a CD-quality file and printing 20x per second a line
+// on the console with the current time. So I guess performance is not such a
+// factor here.
+//#define GET_POSITION_METHOD1
+#define GET_POSITION_METHOD2
+
+
+// The default time for a period in microseconds.
+// For very small buffers, only 2 periods are used.
+#define DEFAULT_PERIOD_TIME 20000 /* 20ms */
+
+///// implemented functions of DirectAudio.h
+
+INT32 DAUDIO_GetDirectAudioDeviceCount() {
+    return (INT32) getAudioDeviceCount();
+}
+
+
+INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex, DirectAudioDeviceDescription* description) {
+    ALSA_AudioDeviceDescription adesc;
+
+    adesc.index = (int) mixerIndex;
+    adesc.strLen = DAUDIO_STRING_LENGTH;
+
+    adesc.maxSimultaneousLines = (int*) (&(description->maxSimulLines));
+    adesc.deviceID = &(description->deviceID);
+    adesc.name = description->name;
+    adesc.vendor = description->vendor;
+    adesc.description = description->description;
+    adesc.version = description->version;
+
+    return getAudioDeviceDescriptionByIndex(&adesc);
+}
+
+#define MAX_BIT_INDEX 6
+// returns
+// 6: for anything above 24-bit
+// 5: for 4 bytes sample size, 24-bit
+// 4: for 3 bytes sample size, 24-bit
+// 3: for 3 bytes sample size, 20-bit
+// 2: for 2 bytes sample size, 16-bit
+// 1: for 1 byte sample size, 8-bit
+// 0: for anything else
+int getBitIndex(int sampleSizeInBytes, int significantBits) {
+    if (significantBits > 24) return 6;
+    if (sampleSizeInBytes == 4 && significantBits == 24) return 5;
+    if (sampleSizeInBytes == 3) {
+        if (significantBits == 24) return 4;
+        if (significantBits == 20) return 3;
+    }
+    if (sampleSizeInBytes == 2 && significantBits == 16) return 2;
+    if (sampleSizeInBytes == 1 && significantBits == 8) return 1;
+    return 0;
+}
+
+int getSampleSizeInBytes(int bitIndex, int sampleSizeInBytes) {
+    switch(bitIndex) {
+    case 1: return 1;
+    case 2: return 2;
+    case 3: /* fall through */
+    case 4: return 3;
+    case 5: return 4;
+    }
+    return sampleSizeInBytes;
+}
+
+int getSignificantBits(int bitIndex, int significantBits) {
+    switch(bitIndex) {
+    case 1: return 8;
+    case 2: return 16;
+    case 3: return 20;
+    case 4: /* fall through */
+    case 5: return 24;
+    }
+    return significantBits;
+}
+
+void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
+    snd_pcm_t* handle;
+    snd_pcm_format_mask_t* formatMask;
+    snd_pcm_format_t format;
+    snd_pcm_hw_params_t* hwParams;
+    int handledBits[MAX_BIT_INDEX+1];
+
+    int ret;
+    int sampleSizeInBytes, significantBits, isSigned, isBigEndian, enc;
+    int origSampleSizeInBytes, origSignificantBits;
+    unsigned int channels, minChannels, maxChannels;
+    int rate, bitIndex;
+
+    for (bitIndex = 0; bitIndex <= MAX_BIT_INDEX; bitIndex++) handledBits[bitIndex] = FALSE;
+    if (openPCMfromDeviceID(deviceID, &handle, isSource, TRUE /*query hardware*/) < 0) {
+        return;
+    }
+    ret = snd_pcm_format_mask_malloc(&formatMask);
+    if (ret != 0) {
+        ERROR1("snd_pcm_format_mask_malloc returned error %d\n", ret);
+    } else {
+        ret = snd_pcm_hw_params_malloc(&hwParams);
+        if (ret != 0) {
+            ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
+        } else {
+            ret = snd_pcm_hw_params_any(handle, hwParams);
+            /* snd_pcm_hw_params_any can return a positive value on success too */
+            if (ret < 0) {
+                 ERROR1("snd_pcm_hw_params_any returned error %d\n", ret);
+            } else {
+                /* for the logic following this code, set ret to 0 to indicate success */
+                ret = 0;
+            }
+        }
+        snd_pcm_hw_params_get_format_mask(hwParams, formatMask);
+        if (ret == 0) {
+            ret = snd_pcm_hw_params_get_channels_min(hwParams, &minChannels);
+            if (ret != 0) {
+                ERROR1("snd_pcm_hw_params_get_channels_min returned error %d\n", ret);
+            }
+        }
+        if (ret == 0) {
+            ret = snd_pcm_hw_params_get_channels_max(hwParams, &maxChannels);
+            if (ret != 0) {
+                ERROR1("snd_pcm_hw_params_get_channels_max returned error %d\n", ret);
+            }
+        }
+
+        // since we queried the hw: device, for many soundcards, it will only
+        // report the maximum number of channels (which is the only way to talk
+        // to the hw: device). Since we will, however, open the plughw: device
+        // when opening the Source/TargetDataLine, we can safely assume that
+        // also the channels 1..maxChannels are available.
+#ifdef ALSA_PCM_USE_PLUGHW
+        minChannels = 1;
+#endif
+        if (ret == 0) {
+            // plughw: supports any sample rate
+            rate = -1;
+            for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
+                if (snd_pcm_format_mask_test(formatMask, format)) {
+                    // format exists
+                    if (getFormatFromAlsaFormat(format, &origSampleSizeInBytes,
+                                                &origSignificantBits,
+                                                &isSigned, &isBigEndian, &enc)) {
+                        // now if we use plughw:, we can use any bit size below the
+                        // natively supported ones. Some ALSA drivers only support the maximum
+                        // bit size, so we add any sample rates below the reported one.
+                        // E.g. this iteration reports support for 16-bit.
+                        // getBitIndex will return 2, so it will add entries for
+                        // 16-bit (bitIndex=2) and in the next do-while loop iteration,
+                        // it will decrease bitIndex and will therefore add 8-bit support.
+                        bitIndex = getBitIndex(origSampleSizeInBytes, origSignificantBits);
+                        do {
+                            if (bitIndex == 0
+                                || bitIndex == MAX_BIT_INDEX
+                                || !handledBits[bitIndex]) {
+                                handledBits[bitIndex] = TRUE;
+                                sampleSizeInBytes = getSampleSizeInBytes(bitIndex, origSampleSizeInBytes);
+                                significantBits = getSignificantBits(bitIndex, origSignificantBits);
+                                if (maxChannels - minChannels > MAXIMUM_LISTED_CHANNELS) {
+                                    // avoid too many channels explicitly listed
+                                    // just add -1, min, and max
+                                    DAUDIO_AddAudioFormat(creator, significantBits,
+                                                          -1, -1, rate,
+                                                          enc, isSigned, isBigEndian);
+                                    DAUDIO_AddAudioFormat(creator, significantBits,
+                                                          sampleSizeInBytes * minChannels,
+                                                          minChannels, rate,
+                                                          enc, isSigned, isBigEndian);
+                                    DAUDIO_AddAudioFormat(creator, significantBits,
+                                                          sampleSizeInBytes * maxChannels,
+                                                          maxChannels, rate,
+                                                          enc, isSigned, isBigEndian);
+                                } else {
+                                    for (channels = minChannels; channels <= maxChannels; channels++) {
+                                        DAUDIO_AddAudioFormat(creator, significantBits,
+                                                              sampleSizeInBytes * channels,
+                                                              channels, rate,
+                                                              enc, isSigned, isBigEndian);
+                                    }
+                                }
+                            }
+#ifndef ALSA_PCM_USE_PLUGHW
+                            // without plugin, do not add fake formats
+                            break;
+#endif
+                        } while (--bitIndex > 0);
+                    } else {
+                        TRACE1("could not get format from alsa for format %d\n", format);
+                    }
+                } else {
+                    //TRACE1("Format %d not supported\n", format);
+                }
+            } // for loop
+            snd_pcm_hw_params_free(hwParams);
+        }
+        snd_pcm_format_mask_free(formatMask);
+    }
+    snd_pcm_close(handle);
+}
+
+/** Workaround for cr 7033899, 7030629:
+ * dmix plugin doesn't like flush (snd_pcm_drop) when the buffer is empty
+ * (just opened, underruned or already flushed).
+ * Sometimes it causes PCM falls to -EBADFD error,
+ * sometimes causes bufferSize change.
+ * To prevent unnecessary flushes AlsaPcmInfo::isRunning & isFlushed are used.
+ */
+/* ******* ALSA PCM INFO ******************** */
+typedef struct tag_AlsaPcmInfo {
+    snd_pcm_t* handle;
+    snd_pcm_hw_params_t* hwParams;
+    snd_pcm_sw_params_t* swParams;
+    int bufferSizeInBytes;
+    int frameSize; // storage size in Bytes
+    unsigned int periods;
+    snd_pcm_uframes_t periodSize;
+    short int isRunning;    // see comment above
+    short int isFlushed;    // see comment above
+#ifdef GET_POSITION_METHOD2
+    // to be used exclusively by getBytePosition!
+    snd_pcm_status_t* positionStatus;
+#endif
+} AlsaPcmInfo;
+
+
+int setStartThresholdNoCommit(AlsaPcmInfo* info, int useThreshold) {
+    int ret;
+    int threshold;
+
+    if (useThreshold) {
+        // start device whenever anything is written to the buffer
+        threshold = 1;
+    } else {
+        // never start the device automatically
+        threshold = 2000000000; /* near UINT_MAX */
+    }
+    ret = snd_pcm_sw_params_set_start_threshold(info->handle, info->swParams, threshold);
+    if (ret < 0) {
+        ERROR1("Unable to set start threshold mode: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    return TRUE;
+}
+
+int setStartThreshold(AlsaPcmInfo* info, int useThreshold) {
+    int ret = 0;
+
+    if (!setStartThresholdNoCommit(info, useThreshold)) {
+        ret = -1;
+    }
+    if (ret == 0) {
+        // commit it
+        ret = snd_pcm_sw_params(info->handle, info->swParams);
+        if (ret < 0) {
+            ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
+        }
+    }
+    return (ret == 0)?TRUE:FALSE;
+}
+
+
+// returns TRUE if successful
+int setHWParams(AlsaPcmInfo* info,
+                float sampleRate,
+                int channels,
+                int bufferSizeInFrames,
+                snd_pcm_format_t format) {
+    unsigned int rrate, periodTime, periods;
+    int ret, dir;
+    snd_pcm_uframes_t alsaBufferSizeInFrames = (snd_pcm_uframes_t) bufferSizeInFrames;
+
+    /* choose all parameters */
+    ret = snd_pcm_hw_params_any(info->handle, info->hwParams);
+    if (ret < 0) {
+        ERROR1("Broken configuration: no configurations available: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    /* set the interleaved read/write format */
+    ret = snd_pcm_hw_params_set_access(info->handle, info->hwParams, SND_PCM_ACCESS_RW_INTERLEAVED);
+    if (ret < 0) {
+        ERROR1("SND_PCM_ACCESS_RW_INTERLEAVED access type not available: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    /* set the sample format */
+    ret = snd_pcm_hw_params_set_format(info->handle, info->hwParams, format);
+    if (ret < 0) {
+        ERROR1("Sample format not available: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    /* set the count of channels */
+    ret = snd_pcm_hw_params_set_channels(info->handle, info->hwParams, channels);
+    if (ret < 0) {
+        ERROR2("Channels count (%d) not available: %s\n", channels, snd_strerror(ret));
+        return FALSE;
+    }
+    /* set the stream rate */
+    rrate = (int) (sampleRate + 0.5f);
+    dir = 0;
+    ret = snd_pcm_hw_params_set_rate_near(info->handle, info->hwParams, &rrate, &dir);
+    if (ret < 0) {
+        ERROR2("Rate %dHz not available for playback: %s\n", (int) (sampleRate+0.5f), snd_strerror(ret));
+        return FALSE;
+    }
+    if ((rrate-sampleRate > 2) || (rrate-sampleRate < - 2)) {
+        ERROR2("Rate doesn't match (requested %2.2fHz, got %dHz)\n", sampleRate, rrate);
+        return FALSE;
+    }
+    /* set the buffer time */
+    ret = snd_pcm_hw_params_set_buffer_size_near(info->handle, info->hwParams, &alsaBufferSizeInFrames);
+    if (ret < 0) {
+        ERROR2("Unable to set buffer size to %d frames: %s\n",
+               (int) alsaBufferSizeInFrames, snd_strerror(ret));
+        return FALSE;
+    }
+    bufferSizeInFrames = (int) alsaBufferSizeInFrames;
+    /* set the period time */
+    if (bufferSizeInFrames > 1024) {
+        dir = 0;
+        periodTime = DEFAULT_PERIOD_TIME;
+        ret = snd_pcm_hw_params_set_period_time_near(info->handle, info->hwParams, &periodTime, &dir);
+        if (ret < 0) {
+            ERROR2("Unable to set period time to %d: %s\n", DEFAULT_PERIOD_TIME, snd_strerror(ret));
+            return FALSE;
+        }
+    } else {
+        /* set the period count for very small buffer sizes to 2 */
+        dir = 0;
+        periods = 2;
+        ret = snd_pcm_hw_params_set_periods_near(info->handle, info->hwParams, &periods, &dir);
+        if (ret < 0) {
+            ERROR2("Unable to set period count to %d: %s\n", /*periods*/ 2, snd_strerror(ret));
+            return FALSE;
+        }
+    }
+    /* write the parameters to device */
+    ret = snd_pcm_hw_params(info->handle, info->hwParams);
+    if (ret < 0) {
+        ERROR1("Unable to set hw params: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    return TRUE;
+}
+
+// returns 1 if successful
+int setSWParams(AlsaPcmInfo* info) {
+    int ret;
+
+    /* get the current swparams */
+    ret = snd_pcm_sw_params_current(info->handle, info->swParams);
+    if (ret < 0) {
+        ERROR1("Unable to determine current swparams: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    /* never start the transfer automatically */
+    if (!setStartThresholdNoCommit(info, FALSE /* don't use threshold */)) {
+        return FALSE;
+    }
+
+    /* allow the transfer when at least period_size samples can be processed */
+    ret = snd_pcm_sw_params_set_avail_min(info->handle, info->swParams, info->periodSize);
+    if (ret < 0) {
+        ERROR1("Unable to set avail min for playback: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    /* write the parameters to the playback device */
+    ret = snd_pcm_sw_params(info->handle, info->swParams);
+    if (ret < 0) {
+        ERROR1("Unable to set sw params: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    return TRUE;
+}
+
+static snd_output_t* ALSA_OUTPUT = NULL;
+
+void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
+                  int encoding, float sampleRate, int sampleSizeInBits,
+                  int frameSize, int channels,
+                  int isSigned, int isBigEndian, int bufferSizeInBytes) {
+    snd_pcm_format_mask_t* formatMask;
+    snd_pcm_format_t format;
+    int dir;
+    int ret = 0;
+    AlsaPcmInfo* info = NULL;
+    /* snd_pcm_uframes_t is 64 bit on 64-bit systems */
+    snd_pcm_uframes_t alsaBufferSizeInFrames = 0;
+
+
+    TRACE0("> DAUDIO_Open\n");
+#ifdef USE_TRACE
+    // for using ALSA debug dump methods
+    if (ALSA_OUTPUT == NULL) {
+        snd_output_stdio_attach(&ALSA_OUTPUT, stdout, 0);
+    }
+#endif
+    if (channels <= 0) {
+        ERROR1("ERROR: Invalid number of channels=%d!\n", channels);
+        return NULL;
+    }
+    info = (AlsaPcmInfo*) malloc(sizeof(AlsaPcmInfo));
+    if (!info) {
+        ERROR0("Out of memory\n");
+        return NULL;
+    }
+    memset(info, 0, sizeof(AlsaPcmInfo));
+    // initial values are: stopped, flushed
+    info->isRunning = 0;
+    info->isFlushed = 1;
+
+    ret = openPCMfromDeviceID(deviceID, &(info->handle), isSource, FALSE /* do open device*/);
+    if (ret == 0) {
+        // set to blocking mode
+        snd_pcm_nonblock(info->handle, 0);
+        ret = snd_pcm_hw_params_malloc(&(info->hwParams));
+        if (ret != 0) {
+            ERROR1("  snd_pcm_hw_params_malloc returned error %d\n", ret);
+        } else {
+            ret = -1;
+            if (getAlsaFormatFromFormat(&format, frameSize / channels, sampleSizeInBits,
+                                        isSigned, isBigEndian, encoding)) {
+                if (setHWParams(info,
+                                sampleRate,
+                                channels,
+                                bufferSizeInBytes / frameSize,
+                                format)) {
+                    info->frameSize = frameSize;
+                    ret = snd_pcm_hw_params_get_period_size(info->hwParams, &info->periodSize, &dir);
+                    if (ret < 0) {
+                        ERROR1("ERROR: snd_pcm_hw_params_get_period: %s\n", snd_strerror(ret));
+                    }
+                    snd_pcm_hw_params_get_periods(info->hwParams, &(info->periods), &dir);
+                    snd_pcm_hw_params_get_buffer_size(info->hwParams, &alsaBufferSizeInFrames);
+                    info->bufferSizeInBytes = (int) alsaBufferSizeInFrames * frameSize;
+                    TRACE3("  DAUDIO_Open: period size = %d frames, periods = %d. Buffer size: %d bytes.\n",
+                           (int) info->periodSize, info->periods, info->bufferSizeInBytes);
+                }
+            }
+        }
+        if (ret == 0) {
+            // set software parameters
+            ret = snd_pcm_sw_params_malloc(&(info->swParams));
+            if (ret != 0) {
+                ERROR1("snd_pcm_hw_params_malloc returned error %d\n", ret);
+            } else {
+                if (!setSWParams(info)) {
+                    ret = -1;
+                }
+            }
+        }
+        if (ret == 0) {
+            // prepare device
+            ret = snd_pcm_prepare(info->handle);
+            if (ret < 0) {
+                ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
+            }
+        }
+
+#ifdef GET_POSITION_METHOD2
+        if (ret == 0) {
+            ret = snd_pcm_status_malloc(&(info->positionStatus));
+            if (ret != 0) {
+                ERROR1("ERROR in snd_pcm_status_malloc: %s\n", snd_strerror(ret));
+            }
+        }
+#endif
+    }
+    if (ret != 0) {
+        DAUDIO_Close((void*) info, isSource);
+        info = NULL;
+    } else {
+        // set to non-blocking mode
+        snd_pcm_nonblock(info->handle, 1);
+        TRACE1("< DAUDIO_Open: Opened device successfully. Handle=%p\n",
+               (void*) info->handle);
+    }
+    return (void*) info;
+}
+
+#ifdef USE_TRACE
+void printState(snd_pcm_state_t state) {
+    if (state == SND_PCM_STATE_OPEN) {
+        TRACE0("State: SND_PCM_STATE_OPEN\n");
+    }
+    else if (state == SND_PCM_STATE_SETUP) {
+        TRACE0("State: SND_PCM_STATE_SETUP\n");
+    }
+    else if (state == SND_PCM_STATE_PREPARED) {
+        TRACE0("State: SND_PCM_STATE_PREPARED\n");
+    }
+    else if (state == SND_PCM_STATE_RUNNING) {
+        TRACE0("State: SND_PCM_STATE_RUNNING\n");
+    }
+    else if (state == SND_PCM_STATE_XRUN) {
+        TRACE0("State: SND_PCM_STATE_XRUN\n");
+    }
+    else if (state == SND_PCM_STATE_DRAINING) {
+        TRACE0("State: SND_PCM_STATE_DRAINING\n");
+    }
+    else if (state == SND_PCM_STATE_PAUSED) {
+        TRACE0("State: SND_PCM_STATE_PAUSED\n");
+    }
+    else if (state == SND_PCM_STATE_SUSPENDED) {
+        TRACE0("State: SND_PCM_STATE_SUSPENDED\n");
+    }
+}
+#endif
+
+int DAUDIO_Start(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    int ret;
+    snd_pcm_state_t state;
+
+    TRACE0("> DAUDIO_Start\n");
+    // set to blocking mode
+    snd_pcm_nonblock(info->handle, 0);
+    // set start mode so that it always starts as soon as data is there
+    setStartThreshold(info, TRUE /* use threshold */);
+    state = snd_pcm_state(info->handle);
+    if (state == SND_PCM_STATE_PAUSED) {
+        // in case it was stopped previously
+        TRACE0("  Un-pausing...\n");
+        ret = snd_pcm_pause(info->handle, FALSE);
+        if (ret != 0) {
+            ERROR2("  NOTE: error in snd_pcm_pause:%d: %s\n", ret, snd_strerror(ret));
+        }
+    }
+    if (state == SND_PCM_STATE_SUSPENDED) {
+        TRACE0("  Resuming...\n");
+        ret = snd_pcm_resume(info->handle);
+        if (ret < 0) {
+            if ((ret != -EAGAIN) && (ret != -ENOSYS)) {
+                ERROR2("  ERROR: error in snd_pcm_resume:%d: %s\n", ret, snd_strerror(ret));
+            }
+        }
+    }
+    if (state == SND_PCM_STATE_SETUP) {
+        TRACE0("need to call prepare again...\n");
+        // prepare device
+        ret = snd_pcm_prepare(info->handle);
+        if (ret < 0) {
+            ERROR1("ERROR: snd_pcm_prepare: %s\n", snd_strerror(ret));
+        }
+    }
+    // in case there is still data in the buffers
+    ret = snd_pcm_start(info->handle);
+    if (ret != 0) {
+        if (ret != -EPIPE) {
+            ERROR2("  NOTE: error in snd_pcm_start: %d: %s\n", ret, snd_strerror(ret));
+        }
+    }
+    // set to non-blocking mode
+    ret = snd_pcm_nonblock(info->handle, 1);
+    if (ret != 0) {
+        ERROR1("  ERROR in snd_pcm_nonblock: %s\n", snd_strerror(ret));
+    }
+    state = snd_pcm_state(info->handle);
+#ifdef USE_TRACE
+    printState(state);
+#endif
+    ret = (state == SND_PCM_STATE_PREPARED)
+        || (state == SND_PCM_STATE_RUNNING)
+        || (state == SND_PCM_STATE_XRUN)
+        || (state == SND_PCM_STATE_SUSPENDED);
+    if (ret) {
+        info->isRunning = 1;
+        // source line should keep isFlushed value until Write() is called;
+        // for target data line reset it right now.
+        if (!isSource) {
+            info->isFlushed = 0;
+        }
+    }
+    TRACE1("< DAUDIO_Start %s\n", ret?"success":"error");
+    return ret?TRUE:FALSE;
+}
+
+int DAUDIO_Stop(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    int ret;
+
+    TRACE0("> DAUDIO_Stop\n");
+    // set to blocking mode
+    snd_pcm_nonblock(info->handle, 0);
+    setStartThreshold(info, FALSE /* don't use threshold */); // device will not start after buffer xrun
+    ret = snd_pcm_pause(info->handle, 1);
+    // set to non-blocking mode
+    snd_pcm_nonblock(info->handle, 1);
+    if (ret != 0) {
+        ERROR1("ERROR in snd_pcm_pause: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+    info->isRunning = 0;
+    TRACE0("< DAUDIO_Stop success\n");
+    return TRUE;
+}
+
+void DAUDIO_Close(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+
+    TRACE0("DAUDIO_Close\n");
+    if (info != NULL) {
+        if (info->handle != NULL) {
+            snd_pcm_close(info->handle);
+        }
+        if (info->hwParams) {
+            snd_pcm_hw_params_free(info->hwParams);
+        }
+        if (info->swParams) {
+            snd_pcm_sw_params_free(info->swParams);
+        }
+#ifdef GET_POSITION_METHOD2
+        if (info->positionStatus) {
+            snd_pcm_status_free(info->positionStatus);
+        }
+#endif
+        free(info);
+    }
+}
+
+/*
+ * Underrun and suspend recovery
+ * returns
+ * 0:  exit native and return 0
+ * 1:  try again to write/read
+ * -1: error - exit native with return value -1
+ */
+int xrun_recovery(AlsaPcmInfo* info, int err) {
+    int ret;
+
+    if (err == -EPIPE) {    /* underrun / overflow */
+        TRACE0("xrun_recovery: underrun/overflow.\n");
+        ret = snd_pcm_prepare(info->handle);
+        if (ret < 0) {
+            ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
+            return -1;
+        }
+        return 1;
+    } else if (err == -ESTRPIPE) {
+        TRACE0("xrun_recovery: suspended.\n");
+        ret = snd_pcm_resume(info->handle);
+        if (ret < 0) {
+            if (ret == -EAGAIN) {
+                return 0; /* wait until the suspend flag is released */
+            }
+            return -1;
+        }
+        ret = snd_pcm_prepare(info->handle);
+        if (ret < 0) {
+            ERROR1("Can't recover from underrun/overflow, prepare failed: %s\n", snd_strerror(ret));
+            return -1;
+        }
+        return 1;
+    } else if (err == -EAGAIN) {
+        TRACE0("xrun_recovery: EAGAIN try again flag.\n");
+        return 0;
+    }
+
+    TRACE2("xrun_recovery: unexpected error %d: %s\n", err, snd_strerror(err));
+    return -1;
+}
+
+// returns -1 on error
+int DAUDIO_Write(void* id, char* data, int byteSize) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    int ret, count;
+    snd_pcm_sframes_t frameSize, writtenFrames;
+
+    TRACE1("> DAUDIO_Write %d bytes\n", byteSize);
+
+    /* sanity */
+    if (byteSize <= 0 || info->frameSize <= 0) {
+        ERROR2(" DAUDIO_Write: byteSize=%d, frameSize=%d!\n",
+               (int) byteSize, (int) info->frameSize);
+        TRACE0("< DAUDIO_Write returning -1\n");
+        return -1;
+    }
+
+    count = 2; // maximum number of trials to recover from underrun
+    //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
+    frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
+    do {
+        writtenFrames = snd_pcm_writei(info->handle, (const void*) data, (snd_pcm_uframes_t) frameSize);
+
+        if (writtenFrames < 0) {
+            ret = xrun_recovery(info, (int) writtenFrames);
+            if (ret <= 0) {
+                TRACE1("DAUDIO_Write: xrun recovery returned %d -> return.\n", ret);
+                return ret;
+            }
+            if (count-- <= 0) {
+                ERROR0("DAUDIO_Write: too many attempts to recover from xrun/suspend\n");
+                return -1;
+            }
+        } else {
+            break;
+        }
+    } while (TRUE);
+    //ret =  snd_pcm_frames_to_bytes(info->handle, writtenFrames);
+
+    if (writtenFrames > 0) {
+        // reset "flushed" flag
+        info->isFlushed = 0;
+    }
+
+    ret =  (int) (writtenFrames * info->frameSize);
+    TRACE1("< DAUDIO_Write: returning %d bytes.\n", ret);
+    return ret;
+}
+
+// returns -1 on error
+int DAUDIO_Read(void* id, char* data, int byteSize) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    int ret, count;
+    snd_pcm_sframes_t frameSize, readFrames;
+
+    TRACE1("> DAUDIO_Read %d bytes\n", byteSize);
+    /*TRACE3("  info=%p, data=%p, byteSize=%d\n",
+      (void*) info, (void*) data, (int) byteSize);
+      TRACE2("  info->frameSize=%d, info->handle=%p\n",
+      (int) info->frameSize, (void*) info->handle);
+    */
+    /* sanity */
+    if (byteSize <= 0 || info->frameSize <= 0) {
+        ERROR2(" DAUDIO_Read: byteSize=%d, frameSize=%d!\n",
+               (int) byteSize, (int) info->frameSize);
+        TRACE0("< DAUDIO_Read returning -1\n");
+        return -1;
+    }
+    if (!info->isRunning && info->isFlushed) {
+        // PCM has nothing to read
+        return 0;
+    }
+
+    count = 2; // maximum number of trials to recover from error
+    //frameSize = snd_pcm_bytes_to_frames(info->handle, byteSize);
+    frameSize = (snd_pcm_sframes_t) (byteSize / info->frameSize);
+    do {
+        readFrames = snd_pcm_readi(info->handle, (void*) data, (snd_pcm_uframes_t) frameSize);
+        if (readFrames < 0) {
+            ret = xrun_recovery(info, (int) readFrames);
+            if (ret <= 0) {
+                TRACE1("DAUDIO_Read: xrun recovery returned %d -> return.\n", ret);
+                return ret;
+            }
+            if (count-- <= 0) {
+                ERROR0("DAUDIO_Read: too many attempts to recover from xrun/suspend\n");
+                return -1;
+            }
+        } else {
+            break;
+        }
+    } while (TRUE);
+    //ret =  snd_pcm_frames_to_bytes(info->handle, readFrames);
+    ret =  (int) (readFrames * info->frameSize);
+    TRACE1("< DAUDIO_Read: returning %d bytes.\n", ret);
+    return ret;
+}
+
+
+int DAUDIO_GetBufferSize(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+
+    return info->bufferSizeInBytes;
+}
+
+int DAUDIO_StillDraining(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    snd_pcm_state_t state;
+
+    state = snd_pcm_state(info->handle);
+    //printState(state);
+    //TRACE1("Still draining: %s\n", (state != SND_PCM_STATE_XRUN)?"TRUE":"FALSE");
+    return (state == SND_PCM_STATE_RUNNING)?TRUE:FALSE;
+}
+
+
+int DAUDIO_Flush(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    int ret;
+
+    TRACE0("DAUDIO_Flush\n");
+
+    if (info->isFlushed) {
+        // nothing to drop
+        return 1;
+    }
+
+    ret = snd_pcm_drop(info->handle);
+    if (ret != 0) {
+        ERROR1("ERROR in snd_pcm_drop: %s\n", snd_strerror(ret));
+        return FALSE;
+    }
+
+    info->isFlushed = 1;
+    if (info->isRunning) {
+        ret = DAUDIO_Start(id, isSource);
+    }
+    return ret;
+}
+
+int DAUDIO_GetAvailable(void* id, int isSource) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    snd_pcm_sframes_t availableInFrames;
+    snd_pcm_state_t state;
+    int ret;
+
+    state = snd_pcm_state(info->handle);
+    if (info->isFlushed || state == SND_PCM_STATE_XRUN) {
+        // if in xrun state then we have the entire buffer available,
+        // not 0 as alsa reports
+        ret = info->bufferSizeInBytes;
+    } else {
+        availableInFrames = snd_pcm_avail_update(info->handle);
+        if (availableInFrames < 0) {
+            ret = 0;
+        } else {
+            //ret = snd_pcm_frames_to_bytes(info->handle, availableInFrames);
+            ret = (int) (availableInFrames * info->frameSize);
+        }
+    }
+    TRACE1("DAUDIO_GetAvailable returns %d bytes\n", ret);
+    return ret;
+}
+
+INT64 estimatePositionFromAvail(AlsaPcmInfo* info, int isSource, INT64 javaBytePos, int availInBytes) {
+    // estimate the current position with the buffer size and
+    // the available bytes to read or write in the buffer.
+    // not an elegant solution - bytePos will stop on xruns,
+    // and in race conditions it may jump backwards
+    // Advantage is that it is indeed based on the samples that go through
+    // the system (rather than time-based methods)
+    if (isSource) {
+        // javaBytePos is the position that is reached when the current
+        // buffer is played completely
+        return (INT64) (javaBytePos - info->bufferSizeInBytes + availInBytes);
+    } else {
+        // javaBytePos is the position that was when the current buffer was empty
+        return (INT64) (javaBytePos + availInBytes);
+    }
+}
+
+INT64 DAUDIO_GetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+    AlsaPcmInfo* info = (AlsaPcmInfo*) id;
+    int ret;
+    INT64 result = javaBytePos;
+    snd_pcm_state_t state;
+    state = snd_pcm_state(info->handle);
+
+    if (!info->isFlushed && state != SND_PCM_STATE_XRUN) {
+#ifdef GET_POSITION_METHOD2
+        snd_timestamp_t* ts;
+        snd_pcm_uframes_t framesAvail;
+
+        // note: slight race condition if this is called simultaneously from 2 threads
+        ret = snd_pcm_status(info->handle, info->positionStatus);
+        if (ret != 0) {
+            ERROR1("ERROR in snd_pcm_status: %s\n", snd_strerror(ret));
+            result = javaBytePos;
+        } else {
+            // calculate from time value, or from available bytes
+            framesAvail = snd_pcm_status_get_avail(info->positionStatus);
+            result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
+        }
+#endif
+#ifdef GET_POSITION_METHOD3
+        snd_pcm_uframes_t framesAvail;
+        ret = snd_pcm_avail(info->handle, &framesAvail);
+        if (ret != 0) {
+            ERROR1("ERROR in snd_pcm_avail: %s\n", snd_strerror(ret));
+            result = javaBytePos;
+        } else {
+            result = estimatePositionFromAvail(info, isSource, javaBytePos, framesAvail * info->frameSize);
+        }
+#endif
+#ifdef GET_POSITION_METHOD1
+        result = estimatePositionFromAvail(info, isSource, javaBytePos, DAUDIO_GetAvailable(id, isSource));
+#endif
+    }
+    //printf("getbyteposition: javaBytePos=%d , return=%d\n", (int) javaBytePos, (int) result);
+    return result;
+}
+
+
+
+void DAUDIO_SetBytePosition(void* id, int isSource, INT64 javaBytePos) {
+    /* save to ignore, since GetBytePosition
+     * takes the javaBytePos param into account
+     */
+}
+
+int DAUDIO_RequiresServicing(void* id, int isSource) {
+    // never need servicing on Linux
+    return FALSE;
+}
+
+void DAUDIO_Service(void* id, int isSource) {
+    // never need servicing on Linux
+}
+
+
+#endif // USE_DAUDIO
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2003, 2014, 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.
+ */
+
+//#define USE_ERROR
+//#define USE_TRACE
+
+#include "PLATFORM_API_LinuxOS_ALSA_PCMUtils.h"
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+
+
+
+// callback for iteration through devices
+// returns TRUE if iteration should continue
+// NOTE: cardinfo may be NULL (for "default" device)
+typedef int (*DeviceIteratorPtr)(UINT32 deviceID, snd_pcm_info_t* pcminfo,
+                             snd_ctl_card_info_t* cardinfo, void *userData);
+
+// for each ALSA device, call iterator. userData is passed to the iterator
+// returns total number of iterations
+int iteratePCMDevices(DeviceIteratorPtr iterator, void* userData) {
+    int count = 0;
+    int subdeviceCount;
+    int card, dev, subDev;
+    char devname[16];
+    int err;
+    snd_ctl_t *handle;
+    snd_pcm_t *pcm;
+    snd_pcm_info_t* pcminfo;
+    snd_ctl_card_info_t *cardinfo, *defcardinfo = NULL;
+    UINT32 deviceID;
+    int doContinue = TRUE;
+
+    snd_pcm_info_malloc(&pcminfo);
+    snd_ctl_card_info_malloc(&cardinfo);
+
+    // 1st try "default" device
+    err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
+                       SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+    if (err < 0) {
+        // try with the other direction
+        err = snd_pcm_open(&pcm, ALSA_DEFAULT_DEVICE_NAME,
+                           SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK);
+    }
+    if (err < 0) {
+        ERROR1("ERROR: snd_pcm_open (\"default\"): %s\n", snd_strerror(err));
+    } else {
+        err = snd_pcm_info(pcm, pcminfo);
+        snd_pcm_close(pcm);
+        if (err < 0) {
+            ERROR1("ERROR: snd_pcm_info (\"default\"): %s\n",
+                    snd_strerror(err));
+        } else {
+            // try to get card info
+            card = snd_pcm_info_get_card(pcminfo);
+            if (card >= 0) {
+                sprintf(devname, ALSA_HARDWARE_CARD, card);
+                if (snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK) >= 0) {
+                    if (snd_ctl_card_info(handle, cardinfo) >= 0) {
+                        defcardinfo = cardinfo;
+                    }
+                    snd_ctl_close(handle);
+                }
+            }
+            // call callback function for the device
+            if (iterator != NULL) {
+                doContinue = (*iterator)(ALSA_DEFAULT_DEVICE_ID, pcminfo,
+                                         defcardinfo, userData);
+            }
+            count++;
+        }
+    }
+
+    // iterate cards
+    card = -1;
+    while (doContinue) {
+        if (snd_card_next(&card) < 0) {
+            break;
+        }
+        if (card < 0) {
+            break;
+        }
+        sprintf(devname, ALSA_HARDWARE_CARD, card);
+        TRACE1("Opening alsa device \"%s\"...\n", devname);
+        err = snd_ctl_open(&handle, devname, SND_CTL_NONBLOCK);
+        if (err < 0) {
+            ERROR2("ERROR: snd_ctl_open, card=%d: %s\n",
+                    card, snd_strerror(err));
+        } else {
+            err = snd_ctl_card_info(handle, cardinfo);
+            if (err < 0) {
+                ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n",
+                        card, snd_strerror(err));
+            } else {
+                dev = -1;
+                while (doContinue) {
+                    if (snd_ctl_pcm_next_device(handle, &dev) < 0) {
+                        ERROR0("snd_ctl_pcm_next_device\n");
+                    }
+                    if (dev < 0) {
+                        break;
+                    }
+                    snd_pcm_info_set_device(pcminfo, dev);
+                    snd_pcm_info_set_subdevice(pcminfo, 0);
+                    snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_PLAYBACK);
+                    err = snd_ctl_pcm_info(handle, pcminfo);
+                    if (err == -ENOENT) {
+                        // try with the other direction
+                        snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
+                        err = snd_ctl_pcm_info(handle, pcminfo);
+                    }
+                    if (err < 0) {
+                        if (err != -ENOENT) {
+                            ERROR2("ERROR: snd_ctl_pcm_info, card=%d: %s",
+                                    card, snd_strerror(err));
+                        }
+                    } else {
+                        subdeviceCount = needEnumerateSubdevices(ALSA_PCM) ?
+                            snd_pcm_info_get_subdevices_count(pcminfo) : 1;
+                        if (iterator!=NULL) {
+                            for (subDev = 0; subDev < subdeviceCount; subDev++) {
+                                deviceID = encodeDeviceID(card, dev, subDev);
+                                doContinue = (*iterator)(deviceID, pcminfo,
+                                                         cardinfo, userData);
+                                count++;
+                                if (!doContinue) {
+                                    break;
+                                }
+                            }
+                        } else {
+                            count += subdeviceCount;
+                        }
+                    }
+                } // of while(doContinue)
+            }
+            snd_ctl_close(handle);
+        }
+    }
+    snd_ctl_card_info_free(cardinfo);
+    snd_pcm_info_free(pcminfo);
+    return count;
+}
+
+int getAudioDeviceCount() {
+    initAlsaSupport();
+    return iteratePCMDevices(NULL, NULL);
+}
+
+int deviceInfoIterator(UINT32 deviceID, snd_pcm_info_t* pcminfo,
+                       snd_ctl_card_info_t* cardinfo, void* userData) {
+    char buffer[300];
+    ALSA_AudioDeviceDescription* desc = (ALSA_AudioDeviceDescription*)userData;
+#ifdef ALSA_PCM_USE_PLUGHW
+    int usePlugHw = 1;
+#else
+    int usePlugHw = 0;
+#endif
+
+    initAlsaSupport();
+    if (desc->index == 0) {
+        // we found the device with correct index
+        *(desc->maxSimultaneousLines) = needEnumerateSubdevices(ALSA_PCM) ?
+                1 : snd_pcm_info_get_subdevices_count(pcminfo);
+        *desc->deviceID = deviceID;
+        buffer[0]=' '; buffer[1]='[';
+        // buffer[300] is enough to store the actual device string w/o overrun
+        getDeviceStringFromDeviceID(&buffer[2], deviceID, usePlugHw, ALSA_PCM);
+        strncat(buffer, "]", sizeof(buffer) - strlen(buffer) - 1);
+        strncpy(desc->name,
+                (cardinfo != NULL)
+                    ? snd_ctl_card_info_get_id(cardinfo)
+                    : snd_pcm_info_get_id(pcminfo),
+                desc->strLen - strlen(buffer));
+        strncat(desc->name, buffer, desc->strLen - strlen(desc->name));
+        strncpy(desc->vendor, "ALSA (http://www.alsa-project.org)", desc->strLen);
+        strncpy(desc->description,
+                (cardinfo != NULL)
+                    ? snd_ctl_card_info_get_name(cardinfo)
+                    : snd_pcm_info_get_name(pcminfo),
+                desc->strLen);
+        strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
+        strncat(desc->description, snd_pcm_info_get_id(pcminfo), desc->strLen - strlen(desc->description));
+        strncat(desc->description, ", ", desc->strLen - strlen(desc->description));
+        strncat(desc->description, snd_pcm_info_get_name(pcminfo), desc->strLen - strlen(desc->description));
+        getALSAVersion(desc->version, desc->strLen);
+        TRACE4("Returning %s, %s, %s, %s\n", desc->name, desc->vendor, desc->description, desc->version);
+        return FALSE; // do not continue iteration
+    }
+    desc->index--;
+    return TRUE;
+}
+
+// returns 0 if successful
+int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware) {
+    char buffer[200];
+    int ret;
+
+    initAlsaSupport();
+    getDeviceStringFromDeviceID(buffer, deviceID, !hardware, ALSA_PCM);
+
+    TRACE1("Opening ALSA device %s\n", buffer);
+    ret = snd_pcm_open(handle, buffer,
+                       isSource?SND_PCM_STREAM_PLAYBACK:SND_PCM_STREAM_CAPTURE,
+                       SND_PCM_NONBLOCK);
+    if (ret != 0) {
+        ERROR1("snd_pcm_open returned error code %d \n", ret);
+        *handle = NULL;
+    }
+    return ret;
+}
+
+
+int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc) {
+    initAlsaSupport();
+    TRACE1(" getAudioDeviceDescriptionByIndex(mixerIndex = %d\n", desc->index);
+    iteratePCMDevices(&deviceInfoIterator, desc);
+    return (desc->index == 0)?TRUE:FALSE;
+}
+
+// returns 1 if successful
+// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
+int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
+                            int* sampleSizeInBytes, int* significantBits,
+                            int* isSigned, int* isBigEndian, int* enc) {
+
+    *sampleSizeInBytes = (snd_pcm_format_physical_width(alsaFormat) + 7) / 8;
+    *significantBits = snd_pcm_format_width(alsaFormat);
+
+    // defaults
+    *enc = 0; // PCM
+    *isSigned = (snd_pcm_format_signed(alsaFormat) > 0);
+    *isBigEndian = (snd_pcm_format_big_endian(alsaFormat) > 0);
+
+    // non-PCM formats
+    if (alsaFormat == SND_PCM_FORMAT_MU_LAW) { // Mu-Law
+        *sampleSizeInBytes = 8; *enc = 1; *significantBits = *sampleSizeInBytes;
+    }
+    else if (alsaFormat == SND_PCM_FORMAT_A_LAW) {     // A-Law
+        *sampleSizeInBytes = 8; *enc = 2; *significantBits = *sampleSizeInBytes;
+    }
+    else if (snd_pcm_format_linear(alsaFormat) < 1) {
+        return 0;
+    }
+    return (*sampleSizeInBytes > 0);
+}
+
+// returns 1 if successful
+int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
+                            int sampleSizeInBytes, int significantBits,
+                            int isSigned, int isBigEndian, int enc) {
+    *alsaFormat = SND_PCM_FORMAT_UNKNOWN;
+
+    if (enc == 0) {
+        *alsaFormat = snd_pcm_build_linear_format(significantBits,
+                                                  sampleSizeInBytes * 8,
+                                                  isSigned?0:1,
+                                                  isBigEndian?1:0);
+    }
+    else if ((sampleSizeInBytes == 1) && (significantBits == 8)) {
+        if (enc == 1) { // ULAW
+            *alsaFormat = SND_PCM_FORMAT_MU_LAW;
+        }
+        else if (enc == 2) { // ALAW
+            *alsaFormat = SND_PCM_FORMAT_A_LAW;
+        }
+    }
+    return (*alsaFormat == SND_PCM_FORMAT_UNKNOWN)?0:1;
+}
+
+
+/* end */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_PCMUtils.h	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// define this with a later version of ALSA than 0.9.0rc3
+// (starting from 1.0.0 it became default behaviour)
+#define ALSA_PCM_NEW_HW_PARAMS_API
+#include <alsa/asoundlib.h>
+#include "Utilities.h"
+
+#ifndef PLATFORM_API_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
+#define PLATFORM_API_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
+
+// if this is defined, use plughw: devices
+#define ALSA_PCM_USE_PLUGHW
+//#undef ALSA_PCM_USE_PLUGHW
+
+
+// maximum number of channels that is listed in the formats. If more, than
+// just -1 for channel count is used.
+#define MAXIMUM_LISTED_CHANNELS 32
+
+typedef struct tag_ALSA_AudioDeviceDescription {
+    int index;          // in
+    int strLen;         // in
+    INT32* deviceID;    // out
+    int* maxSimultaneousLines; // out
+    char* name;         // out
+    char* vendor;       // out
+    char* description;  // out
+    char* version;      // out
+} ALSA_AudioDeviceDescription;
+
+
+
+int getAudioDeviceCount();
+int getAudioDeviceDescriptionByIndex(ALSA_AudioDeviceDescription* desc);
+
+// returns ALSA error code, or 0 if successful
+int openPCMfromDeviceID(int deviceID, snd_pcm_t** handle, int isSource, int hardware);
+
+// returns 1 if successful
+// enc: 0 for PCM, 1 for ULAW, 2 for ALAW (see DirectAudio.h)
+int getFormatFromAlsaFormat(snd_pcm_format_t alsaFormat,
+                            int* sampleSizeInBytes, int* significantBits,
+                            int* isSigned, int* isBigEndian, int* enc);
+
+int getAlsaFormatFromFormat(snd_pcm_format_t* alsaFormat,
+                            int sampleSizeInBytes, int significantBits,
+                            int isSigned, int isBigEndian, int enc);
+
+#endif // PLATFORM_API_LINUXOS_ALSA_PCMUTILS_H_INCLUDED
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/linux/native/libjsound/PLATFORM_API_LinuxOS_ALSA_Ports.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#define USE_ERROR
+//#define USE_TRACE
+
+#include "Ports.h"
+#include "PLATFORM_API_LinuxOS_ALSA_CommonUtils.h"
+#include <alsa/asoundlib.h>
+
+#if USE_PORTS == TRUE
+
+#define MAX_ELEMS (300)
+#define MAX_CONTROLS (MAX_ELEMS * 4)
+
+#define CHANNELS_MONO (SND_MIXER_SCHN_LAST + 1)
+#define CHANNELS_STEREO (SND_MIXER_SCHN_LAST + 2)
+
+typedef struct {
+    snd_mixer_elem_t* elem;
+    INT32 portType; /* one of PORT_XXX_xx */
+    char* controlType; /* one of CONTROL_TYPE_xx */
+    /* Values: either SND_MIXER_SCHN_FRONT_xx, CHANNELS_MONO or CHANNELS_STEREO.
+       For SND_MIXER_SCHN_FRONT_xx, exactly this channel is set/retrieved directly.
+       For CHANNELS_MONO, ALSA channel SND_MIXER_SCHN_MONO is set/retrieved directly.
+       For CHANNELS_STEREO, ALSA channels SND_MIXER_SCHN_FRONT_LEFT and SND_MIXER_SCHN_FRONT_RIGHT
+       are set after a calculation that takes balance into account. Retrieved? Average of both
+       channels? (Using a cached value is not a good idea since the value in the HW may have been
+       altered.) */
+    INT32 channel;
+} PortControl;
+
+
+typedef struct tag_PortMixer {
+    snd_mixer_t* mixer_handle;
+    /* Number of array elements used in elems and types. */
+    int numElems;
+    snd_mixer_elem_t** elems;
+    /* Array of port types (PORT_SRC_UNKNOWN etc.). Indices are the same as in elems. */
+    INT32* types;
+    /* Number of array elements used in controls. */
+    int numControls;
+    PortControl* controls;
+} PortMixer;
+
+
+///// implemented functions of Ports.h
+
+INT32 PORT_GetPortMixerCount() {
+    INT32 mixerCount;
+    int card;
+    char devname[16];
+    int err;
+    snd_ctl_t *handle;
+    snd_ctl_card_info_t* info;
+
+    TRACE0("> PORT_GetPortMixerCount\n");
+
+    initAlsaSupport();
+
+    snd_ctl_card_info_malloc(&info);
+    card = -1;
+    mixerCount = 0;
+    if (snd_card_next(&card) >= 0) {
+        while (card >= 0) {
+            sprintf(devname, ALSA_HARDWARE_CARD, card);
+            TRACE1("PORT_GetPortMixerCount: Opening alsa device \"%s\"...\n", devname);
+            err = snd_ctl_open(&handle, devname, 0);
+            if (err < 0) {
+                ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", card, snd_strerror(err));
+            } else {
+                mixerCount++;
+                snd_ctl_close(handle);
+            }
+            if (snd_card_next(&card) < 0) {
+                break;
+            }
+        }
+    }
+    snd_ctl_card_info_free(info);
+    TRACE0("< PORT_GetPortMixerCount\n");
+    return mixerCount;
+}
+
+
+INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) {
+    snd_ctl_t* handle;
+    snd_ctl_card_info_t* card_info;
+    char devname[16];
+    int err;
+    char buffer[100];
+
+    TRACE0("> PORT_GetPortMixerDescription\n");
+    snd_ctl_card_info_malloc(&card_info);
+
+    sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
+    TRACE1("Opening alsa device \"%s\"...\n", devname);
+    err = snd_ctl_open(&handle, devname, 0);
+    if (err < 0) {
+        ERROR2("ERROR: snd_ctl_open, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
+        return FALSE;
+    }
+    err = snd_ctl_card_info(handle, card_info);
+    if (err < 0) {
+        ERROR2("ERROR: snd_ctl_card_info, card=%d: %s\n", (int) mixerIndex, snd_strerror(err));
+    }
+    strncpy(description->name, snd_ctl_card_info_get_id(card_info), PORT_STRING_LENGTH - 1);
+    sprintf(buffer, " [%s]", devname);
+    strncat(description->name, buffer, PORT_STRING_LENGTH - 1 - strlen(description->name));
+    strncpy(description->vendor, "ALSA (http://www.alsa-project.org)", PORT_STRING_LENGTH - 1);
+    strncpy(description->description, snd_ctl_card_info_get_name(card_info), PORT_STRING_LENGTH - 1);
+    strncat(description->description, ", ", PORT_STRING_LENGTH - 1 - strlen(description->description));
+    strncat(description->description, snd_ctl_card_info_get_mixername(card_info), PORT_STRING_LENGTH - 1 - strlen(description->description));
+    getALSAVersion(description->version, PORT_STRING_LENGTH - 1);
+
+    snd_ctl_close(handle);
+    snd_ctl_card_info_free(card_info);
+    TRACE0("< PORT_GetPortMixerDescription\n");
+    return TRUE;
+}
+
+
+void* PORT_Open(INT32 mixerIndex) {
+    char devname[16];
+    snd_mixer_t* mixer_handle;
+    int err;
+    PortMixer* handle;
+
+    TRACE0("> PORT_Open\n");
+    sprintf(devname, ALSA_HARDWARE_CARD, (int) mixerIndex);
+    if ((err = snd_mixer_open(&mixer_handle, 0)) < 0) {
+        ERROR2("Mixer %s open error: %s", devname, snd_strerror(err));
+        return NULL;
+    }
+    if ((err = snd_mixer_attach(mixer_handle, devname)) < 0) {
+        ERROR2("Mixer attach %s error: %s", devname, snd_strerror(err));
+        snd_mixer_close(mixer_handle);
+        return NULL;
+    }
+    if ((err = snd_mixer_selem_register(mixer_handle, NULL, NULL)) < 0) {
+        ERROR1("Mixer register error: %s", snd_strerror(err));
+        snd_mixer_close(mixer_handle);
+        return NULL;
+    }
+    err = snd_mixer_load(mixer_handle);
+    if (err < 0) {
+        ERROR2("Mixer %s load error: %s", devname, snd_strerror(err));
+        snd_mixer_close(mixer_handle);
+        return NULL;
+    }
+    handle = (PortMixer*) calloc(1, sizeof(PortMixer));
+    if (handle == NULL) {
+        ERROR0("malloc() failed.");
+        snd_mixer_close(mixer_handle);
+        return NULL;
+    }
+    handle->numElems = 0;
+    handle->elems = (snd_mixer_elem_t**) calloc(MAX_ELEMS, sizeof(snd_mixer_elem_t*));
+    if (handle->elems == NULL) {
+        ERROR0("malloc() failed.");
+        snd_mixer_close(mixer_handle);
+        free(handle);
+        return NULL;
+    }
+    handle->types = (INT32*) calloc(MAX_ELEMS, sizeof(INT32));
+    if (handle->types == NULL) {
+        ERROR0("malloc() failed.");
+        snd_mixer_close(mixer_handle);
+        free(handle->elems);
+        free(handle);
+        return NULL;
+    }
+    handle->controls = (PortControl*) calloc(MAX_CONTROLS, sizeof(PortControl));
+    if (handle->controls == NULL) {
+        ERROR0("malloc() failed.");
+        snd_mixer_close(mixer_handle);
+        free(handle->elems);
+        free(handle->types);
+        free(handle);
+        return NULL;
+    }
+    handle->mixer_handle = mixer_handle;
+    // necessary to initialize data structures
+    PORT_GetPortCount(handle);
+    TRACE0("< PORT_Open\n");
+    return handle;
+}
+
+
+void PORT_Close(void* id) {
+    TRACE0("> PORT_Close\n");
+    if (id != NULL) {
+        PortMixer* handle = (PortMixer*) id;
+        if (handle->mixer_handle != NULL) {
+            snd_mixer_close(handle->mixer_handle);
+        }
+        if (handle->elems != NULL) {
+            free(handle->elems);
+        }
+        if (handle->types != NULL) {
+            free(handle->types);
+        }
+        if (handle->controls != NULL) {
+            free(handle->controls);
+        }
+        free(handle);
+    }
+    TRACE0("< PORT_Close\n");
+}
+
+
+
+INT32 PORT_GetPortCount(void* id) {
+    PortMixer* portMixer;
+    snd_mixer_elem_t *elem;
+
+    TRACE0("> PORT_GetPortCount\n");
+    if (id == NULL) {
+        // $$mp: Should become a descriptive error code (invalid handle).
+        return -1;
+    }
+    portMixer = (PortMixer*) id;
+    if (portMixer->numElems == 0) {
+        for (elem = snd_mixer_first_elem(portMixer->mixer_handle); elem; elem = snd_mixer_elem_next(elem)) {
+            if (!snd_mixer_selem_is_active(elem))
+                continue;
+            TRACE2("Simple mixer control '%s',%i\n",
+                   snd_mixer_selem_get_name(elem),
+                   snd_mixer_selem_get_index(elem));
+            if (snd_mixer_selem_has_playback_volume(elem)) {
+                portMixer->elems[portMixer->numElems] = elem;
+                portMixer->types[portMixer->numElems] = PORT_DST_UNKNOWN;
+                portMixer->numElems++;
+            }
+            // to prevent buffer overflow
+            if (portMixer->numElems >= MAX_ELEMS) {
+                break;
+            }
+            /* If an element has both playback an capture volume, it is put into the arrays
+               twice. */
+            if (snd_mixer_selem_has_capture_volume(elem)) {
+                portMixer->elems[portMixer->numElems] = elem;
+                portMixer->types[portMixer->numElems] = PORT_SRC_UNKNOWN;
+                portMixer->numElems++;
+            }
+            // to prevent buffer overflow
+            if (portMixer->numElems >= MAX_ELEMS) {
+                break;
+            }
+        }
+    }
+    TRACE0("< PORT_GetPortCount\n");
+    return portMixer->numElems;
+}
+
+
+INT32 PORT_GetPortType(void* id, INT32 portIndex) {
+    PortMixer* portMixer;
+    INT32 type;
+    TRACE0("> PORT_GetPortType\n");
+    if (id == NULL) {
+        // $$mp: Should become a descriptive error code (invalid handle).
+        return -1;
+    }
+    portMixer = (PortMixer*) id;
+    if (portIndex < 0 || portIndex >= portMixer->numElems) {
+        // $$mp: Should become a descriptive error code (index out of bounds).
+        return -1;
+    }
+    type = portMixer->types[portIndex];
+    TRACE0("< PORT_GetPortType\n");
+    return type;
+}
+
+
+INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) {
+    PortMixer* portMixer;
+    const char* nam;
+
+    TRACE0("> PORT_GetPortName\n");
+    if (id == NULL) {
+        // $$mp: Should become a descriptive error code (invalid handle).
+        return -1;
+    }
+    portMixer = (PortMixer*) id;
+    if (portIndex < 0 || portIndex >= portMixer->numElems) {
+        // $$mp: Should become a descriptive error code (index out of bounds).
+        return -1;
+    }
+    nam = snd_mixer_selem_get_name(portMixer->elems[portIndex]);
+    strncpy(name, nam, len - 1);
+    name[len - 1] = 0;
+    TRACE0("< PORT_GetPortName\n");
+    return TRUE;
+}
+
+
+static int isPlaybackFunction(INT32 portType) {
+        return (portType & PORT_DST_MASK);
+}
+
+
+/* Sets portControl to a pointer to the next free array element in the PortControl (pointer)
+   array of the passed portMixer. Returns TRUE if successful. May return FALSE if there is no
+   free slot. In this case, portControl is not altered */
+static int getControlSlot(PortMixer* portMixer, PortControl** portControl) {
+    if (portMixer->numControls >= MAX_CONTROLS) {
+        return FALSE;
+    } else {
+        *portControl = &(portMixer->controls[portMixer->numControls]);
+        portMixer->numControls++;
+        return TRUE;
+    }
+}
+
+
+/* Protect against illegal min-max values, preventing divisions by zero.
+ */
+inline static long getRange(long min, long max) {
+    if (max > min) {
+        return max - min;
+    } else {
+        return 1;
+    }
+}
+
+
+/* Idea: we may specify that if unit is an empty string, the values are linear and if unit is "dB",
+   the values are logarithmic.
+*/
+static void* createVolumeControl(PortControlCreator* creator,
+                                 PortControl* portControl,
+                                 snd_mixer_elem_t* elem, int isPlayback) {
+    void* control;
+    float precision;
+    long min, max;
+
+    if (isPlayback) {
+        snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
+    } else {
+        snd_mixer_selem_get_capture_volume_range(elem, &min, &max);
+    }
+    /* $$mp: The volume values retrieved with the ALSA API are strongly supposed to be logarithmic.
+       So the following calculation is wrong. However, there is no correct calculation, since
+       for equal-distant logarithmic steps, the precision expressed in linear varies over the
+       scale. */
+    precision = 1.0F / getRange(min, max);
+    control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_VOLUME, 0.0F, +1.0F, precision, "");
+    return control;
+}
+
+
+void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) {
+    PortMixer* portMixer;
+    snd_mixer_elem_t* elem;
+    void* control;
+    PortControl* portControl;
+    void* controls[10];
+    int numControls;
+    char* portName;
+    int isPlayback = 0;
+    int isMono;
+    int isStereo;
+    char* type;
+    snd_mixer_selem_channel_id_t channel;
+    memset(controls, 0, sizeof(controls));
+
+    TRACE0("> PORT_GetControls\n");
+    if (id == NULL) {
+        ERROR0("Invalid handle!");
+        // $$mp: an error code should be returned.
+        return;
+    }
+    portMixer = (PortMixer*) id;
+    if (portIndex < 0 || portIndex >= portMixer->numElems) {
+        ERROR0("Port index out of range!");
+        // $$mp: an error code should be returned.
+        return;
+    }
+    numControls = 0;
+    elem = portMixer->elems[portIndex];
+    if (snd_mixer_selem_has_playback_volume(elem) || snd_mixer_selem_has_capture_volume(elem)) {
+        /* Since we've split/duplicated elements with both playback and capture on the recovery
+           of elements, we now can assume that we handle only to deal with either playback or
+           capture. */
+        isPlayback = isPlaybackFunction(portMixer->types[portIndex]);
+        isMono = (isPlayback && snd_mixer_selem_is_playback_mono(elem)) ||
+            (!isPlayback && snd_mixer_selem_is_capture_mono(elem));
+        isStereo = (isPlayback &&
+                    snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
+                    snd_mixer_selem_has_playback_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT)) ||
+            (!isPlayback &&
+             snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_LEFT) &&
+             snd_mixer_selem_has_capture_channel(elem, SND_MIXER_SCHN_FRONT_RIGHT));
+        // single volume control
+        if (isMono || isStereo) {
+            if (getControlSlot(portMixer, &portControl)) {
+                portControl->elem = elem;
+                portControl->portType = portMixer->types[portIndex];
+                portControl->controlType = CONTROL_TYPE_VOLUME;
+                if (isMono) {
+                    portControl->channel = CHANNELS_MONO;
+                } else {
+                    portControl->channel = CHANNELS_STEREO;
+                }
+                control = createVolumeControl(creator, portControl, elem, isPlayback);
+                if (control != NULL) {
+                    controls[numControls++] = control;
+                }
+            }
+        } else { // more than two channels, each channels has its own control.
+            for (channel = SND_MIXER_SCHN_FRONT_LEFT; channel <= SND_MIXER_SCHN_LAST; channel++) {
+                if ((isPlayback && snd_mixer_selem_has_playback_channel(elem, channel)) ||
+                    (!isPlayback && snd_mixer_selem_has_capture_channel(elem, channel))) {
+                    if (getControlSlot(portMixer, &portControl)) {
+                        portControl->elem = elem;
+                        portControl->portType = portMixer->types[portIndex];
+                        portControl->controlType = CONTROL_TYPE_VOLUME;
+                        portControl->channel = channel;
+                        control = createVolumeControl(creator, portControl, elem, isPlayback);
+                        // We wrap in a compound control to provide the channel name.
+                        if (control != NULL) {
+                            /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
+                               declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
+                               to take a const char* parameter. */
+                            control = (creator->newCompoundControl)(creator, (char*) snd_mixer_selem_channel_name(channel), &control, 1);
+                        }
+                        if (control != NULL) {
+                            controls[numControls++] = control;
+                        }
+                    }
+                }
+            }
+        }
+        // BALANCE control
+        if (isStereo) {
+            if (getControlSlot(portMixer, &portControl)) {
+                portControl->elem = elem;
+                portControl->portType = portMixer->types[portIndex];
+                portControl->controlType = CONTROL_TYPE_BALANCE;
+                portControl->channel = CHANNELS_STEREO;
+                /* $$mp: The value for precision is chosen more or less arbitrarily. */
+                control = (creator->newFloatControl)(creator, portControl, CONTROL_TYPE_BALANCE, -1.0F, 1.0F, 0.01F, "");
+                if (control != NULL) {
+                    controls[numControls++] = control;
+                }
+            }
+        }
+    }
+    if (snd_mixer_selem_has_playback_switch(elem) || snd_mixer_selem_has_capture_switch(elem)) {
+        if (getControlSlot(portMixer, &portControl)) {
+            type = isPlayback ? CONTROL_TYPE_MUTE : CONTROL_TYPE_SELECT;
+            portControl->elem = elem;
+            portControl->portType = portMixer->types[portIndex];
+            portControl->controlType = type;
+            control = (creator->newBooleanControl)(creator, portControl, type);
+            if (control != NULL) {
+                controls[numControls++] = control;
+            }
+        }
+    }
+    /* $$mp 2003-09-14: The following cast shouln't be necessary. Instead, the
+       declaration of PORT_NewCompoundControlPtr in Ports.h should be changed
+       to take a const char* parameter. */
+    portName = (char*) snd_mixer_selem_get_name(elem);
+    control = (creator->newCompoundControl)(creator, portName, controls, numControls);
+    if (control != NULL) {
+        (creator->addControl)(creator, control);
+    }
+    TRACE0("< PORT_GetControls\n");
+}
+
+
+INT32 PORT_GetIntValue(void* controlIDV) {
+    PortControl* portControl = (PortControl*) controlIDV;
+    int value = 0;
+    snd_mixer_selem_channel_id_t channel;
+
+    if (portControl != NULL) {
+        switch (portControl->channel) {
+        case CHANNELS_MONO:
+            channel = SND_MIXER_SCHN_MONO;
+            break;
+
+        case CHANNELS_STEREO:
+            channel = SND_MIXER_SCHN_FRONT_LEFT;
+            break;
+
+        default:
+            channel = portControl->channel;
+        }
+        if (portControl->controlType == CONTROL_TYPE_MUTE ||
+            portControl->controlType == CONTROL_TYPE_SELECT) {
+            if (isPlaybackFunction(portControl->portType)) {
+                snd_mixer_selem_get_playback_switch(portControl->elem, channel, &value);
+            } else {
+                snd_mixer_selem_get_capture_switch(portControl->elem, channel, &value);
+            }
+            if (portControl->controlType == CONTROL_TYPE_MUTE) {
+                value = ! value;
+            }
+        } else {
+            ERROR1("PORT_GetIntValue(): inappropriate control type: %s\n",
+                   portControl->controlType);
+        }
+    }
+    return (INT32) value;
+}
+
+
+void PORT_SetIntValue(void* controlIDV, INT32 value) {
+    PortControl* portControl = (PortControl*) controlIDV;
+    snd_mixer_selem_channel_id_t channel;
+
+    if (portControl != NULL) {
+        if (portControl->controlType == CONTROL_TYPE_MUTE) {
+            value = ! value;
+        }
+        if (portControl->controlType == CONTROL_TYPE_MUTE ||
+            portControl->controlType == CONTROL_TYPE_SELECT) {
+            if (isPlaybackFunction(portControl->portType)) {
+                snd_mixer_selem_set_playback_switch_all(portControl->elem, value);
+            } else {
+                snd_mixer_selem_set_capture_switch_all(portControl->elem, value);
+            }
+        } else {
+            ERROR1("PORT_SetIntValue(): inappropriate control type: %s\n",
+                   portControl->controlType);
+        }
+    }
+}
+
+
+static float scaleVolumeValueToNormalized(long value, long min, long max) {
+    return (float) (value - min) / getRange(min, max);
+}
+
+
+static long scaleVolumeValueToHardware(float value, long min, long max) {
+    return (long)(value * getRange(min, max) + min);
+}
+
+
+float getRealVolume(PortControl* portControl,
+                    snd_mixer_selem_channel_id_t channel) {
+    float fValue;
+    long lValue = 0;
+    long min = 0;
+    long max = 0;
+
+    if (isPlaybackFunction(portControl->portType)) {
+        snd_mixer_selem_get_playback_volume_range(portControl->elem,
+                                                  &min, &max);
+        snd_mixer_selem_get_playback_volume(portControl->elem,
+                                            channel, &lValue);
+    } else {
+        snd_mixer_selem_get_capture_volume_range(portControl->elem,
+                                                 &min, &max);
+        snd_mixer_selem_get_capture_volume(portControl->elem,
+                                           channel, &lValue);
+    }
+    fValue = scaleVolumeValueToNormalized(lValue, min, max);
+    return fValue;
+}
+
+
+void setRealVolume(PortControl* portControl,
+                   snd_mixer_selem_channel_id_t channel, float value) {
+    long lValue = 0;
+    long min = 0;
+    long max = 0;
+
+    if (isPlaybackFunction(portControl->portType)) {
+        snd_mixer_selem_get_playback_volume_range(portControl->elem,
+                                                  &min, &max);
+        lValue = scaleVolumeValueToHardware(value, min, max);
+        snd_mixer_selem_set_playback_volume(portControl->elem,
+                                            channel, lValue);
+    } else {
+        snd_mixer_selem_get_capture_volume_range(portControl->elem,
+                                                 &min, &max);
+        lValue = scaleVolumeValueToHardware(value, min, max);
+        snd_mixer_selem_set_capture_volume(portControl->elem,
+                                           channel, lValue);
+    }
+}
+
+
+static float getFakeBalance(PortControl* portControl) {
+    float volL, volR;
+
+    // pan is the ratio of left and right
+    volL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
+    volR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
+    if (volL > volR) {
+        return -1.0f + (volR / volL);
+    }
+    else if (volR > volL) {
+        return 1.0f - (volL / volR);
+    }
+    return 0.0f;
+}
+
+
+static float getFakeVolume(PortControl* portControl) {
+    float valueL;
+    float valueR;
+    float value;
+
+    valueL = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT);
+    valueR = getRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT);
+    // volume is the greater value of both
+    value = valueL > valueR ? valueL : valueR ;
+    return value;
+}
+
+
+/*
+ * sets the unsigned values for left and right volume according to
+ * the given volume (0...1) and balance (-1..0..+1)
+ */
+static void setFakeVolume(PortControl* portControl, float vol, float bal) {
+    float volumeLeft;
+    float volumeRight;
+
+    if (bal < 0.0f) {
+        volumeLeft = vol;
+        volumeRight = vol * (bal + 1.0f);
+    } else {
+        volumeLeft = vol * (1.0f - bal);
+        volumeRight = vol;
+    }
+    setRealVolume(portControl, SND_MIXER_SCHN_FRONT_LEFT, volumeLeft);
+    setRealVolume(portControl, SND_MIXER_SCHN_FRONT_RIGHT, volumeRight);
+}
+
+
+float PORT_GetFloatValue(void* controlIDV) {
+    PortControl* portControl = (PortControl*) controlIDV;
+    float value = 0.0F;
+
+    if (portControl != NULL) {
+        if (portControl->controlType == CONTROL_TYPE_VOLUME) {
+            switch (portControl->channel) {
+            case CHANNELS_MONO:
+                value = getRealVolume(portControl, SND_MIXER_SCHN_MONO);
+                break;
+
+            case CHANNELS_STEREO:
+                value = getFakeVolume(portControl);
+                break;
+
+            default:
+                value = getRealVolume(portControl, portControl->channel);
+            }
+        } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
+            if (portControl->channel == CHANNELS_STEREO) {
+                value = getFakeBalance(portControl);
+            } else {
+                ERROR0("PORT_GetFloatValue(): Balance only allowed for stereo channels!\n");
+            }
+        } else {
+            ERROR1("PORT_GetFloatValue(): inappropriate control type: %s!\n",
+                   portControl->controlType);
+        }
+    }
+    return value;
+}
+
+
+void PORT_SetFloatValue(void* controlIDV, float value) {
+    PortControl* portControl = (PortControl*) controlIDV;
+
+    if (portControl != NULL) {
+        if (portControl->controlType == CONTROL_TYPE_VOLUME) {
+            switch (portControl->channel) {
+            case CHANNELS_MONO:
+                setRealVolume(portControl, SND_MIXER_SCHN_MONO, value);
+                break;
+
+            case CHANNELS_STEREO:
+                setFakeVolume(portControl, value, getFakeBalance(portControl));
+                break;
+
+            default:
+                setRealVolume(portControl, portControl->channel, value);
+            }
+        } else if (portControl->controlType == CONTROL_TYPE_BALANCE) {
+            if (portControl->channel == CHANNELS_STEREO) {
+                setFakeVolume(portControl, getFakeVolume(portControl), value);
+            } else {
+                ERROR0("PORT_SetFloatValue(): Balance only allowed for stereo channels!\n");
+            }
+        } else {
+            ERROR1("PORT_SetFloatValue(): inappropriate control type: %s!\n",
+                   portControl->controlType);
+        }
+    }
+}
+
+
+#endif // USE_PORTS
--- a/src/java.desktop/share/classes/com/sun/media/sound/Platform.java	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.desktop/share/classes/com/sun/media/sound/Platform.java	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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,23 +38,9 @@
 final class Platform {
 
     // native library we need to load
-    private static final String libNameMain     = "jsound";
-    private static final String libNameALSA     = "jsoundalsa";
-    private static final String libNameDSound   = "jsoundds";
+    private static final String libName = "jsound";
 
-    // extra libs handling: bit flags for each different library
-    public static final int LIB_MAIN     = 1;
-    public static final int LIB_ALSA     = 2;
-    public static final int LIB_DSOUND   = 4;
-
-    // bit field of the constants above. Willbe set in loadLibraries
-    private static int loadedLibs = 0;
-
-    // features: the main native library jsound reports which feature is
-    // contained in which lib
-    public static final int FEATURE_MIDIIO       = 1;
-    public static final int FEATURE_PORTS        = 2;
-    public static final int FEATURE_DIRECT_AUDIO = 3;
+    private static boolean isNativeLibLoaded;
 
     // SYSTEM CHARACTERISTICS
     // vary according to hardware architecture
@@ -66,7 +52,6 @@
         if(Printer.trace)Printer.trace(">> Platform.java: static");
 
         loadLibraries();
-        readProperties();
     }
 
     /**
@@ -95,72 +80,37 @@
     private static void loadLibraries() {
         if(Printer.trace)Printer.trace(">>Platform.loadLibraries");
 
-        // load the main library
-        AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-            System.loadLibrary(libNameMain);
-            return null;
-        });
-        // just for the heck of it...
-        loadedLibs |= LIB_MAIN;
-
-        // now try to load extra libs. They are defined at compile time in the Makefile
-        // with the define EXTRA_SOUND_JNI_LIBS
-        String extraLibs = nGetExtraLibraries();
-        // the string is the libraries, separated by white space
-        StringTokenizer st = new StringTokenizer(extraLibs);
-        while (st.hasMoreTokens()) {
-            final String lib = st.nextToken();
-            try {
-                AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
-                    System.loadLibrary(lib);
-                    return null;
-                });
-
-                if (lib.equals(libNameALSA)) {
-                    loadedLibs |= LIB_ALSA;
-                    if (Printer.debug) Printer.debug("Loaded ALSA lib successfully.");
-                } else if (lib.equals(libNameDSound)) {
-                    loadedLibs |= LIB_DSOUND;
-                    if (Printer.debug) Printer.debug("Loaded DirectSound lib successfully.");
-                } else {
-                    if (Printer.err) Printer.err("Loaded unknown lib '"+lib+"' successfully.");
-                }
-            } catch (Throwable t) {
-                if (Printer.err) Printer.err("Couldn't load library "+lib+": "+t.toString());
-            }
+        // load the native library
+        isNativeLibLoaded = true;
+        try {
+            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
+                System.loadLibrary(libName);
+                return null;
+            });
+        } catch (Throwable t) {
+            if (Printer.err) Printer.err("Couldn't load library "+libName+": "+t.toString());
+            isNativeLibLoaded = false;
+        }
+        if (isNativeLibLoaded) {
+            bigEndian = nIsBigEndian();
         }
     }
 
     static boolean isMidiIOEnabled() {
-        return isFeatureLibLoaded(FEATURE_MIDIIO);
+        if (Printer.debug) Printer.debug("Platform: Checking for MidiIO; library is loaded=" + isNativeLibLoaded);
+        return isNativeLibLoaded;
     }
 
     static boolean isPortsEnabled() {
-        return isFeatureLibLoaded(FEATURE_PORTS);
+        if (Printer.debug) Printer.debug("Platform: Checking for Ports; library is loaded=" + isNativeLibLoaded);
+        return isNativeLibLoaded;
     }
 
     static boolean isDirectAudioEnabled() {
-        return isFeatureLibLoaded(FEATURE_DIRECT_AUDIO);
+        if (Printer.debug) Printer.debug("Platform: Checking for DirectAudio; library is loaded=" + isNativeLibLoaded);
+        return isNativeLibLoaded;
     }
 
-    private static boolean isFeatureLibLoaded(int feature) {
-        if (Printer.debug) Printer.debug("Platform: Checking for feature "+feature+"...");
-        int requiredLib = nGetLibraryForFeature(feature);
-        boolean isLoaded = (requiredLib != 0) && ((loadedLibs & requiredLib) == requiredLib);
-        if (Printer.debug) Printer.debug("          ...needs library "+requiredLib+". Result is loaded="+isLoaded);
-        return isLoaded;
-    }
-
-    // the following native methods are implemented in Platform.c
+    // the following native method is implemented in Platform.c
     private static native boolean nIsBigEndian();
-    private static native String nGetExtraLibraries();
-    private static native int nGetLibraryForFeature(int feature);
-
-    /**
-     * Read the required system properties.
-     */
-    private static void readProperties() {
-        // $$fb 2002-03-06: implement check for endianness in native. Facilitates porting !
-        bigEndian = nIsBigEndian();
-    }
 }
--- a/src/java.desktop/share/native/libjsound/Platform.c	Fri Mar 23 11:18:39 2018 +0530
+++ b/src/java.desktop/share/native/libjsound/Platform.c	Fri Mar 23 11:14:43 2018 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 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
@@ -41,83 +41,3 @@
 JNIEXPORT jboolean JNICALL Java_com_sun_media_sound_Platform_nIsBigEndian(JNIEnv *env, jclass clss) {
     return UTIL_IsBigEndianPlatform();
 }
-
-/*
- * Class:     com_sun_media_sound_Platform
- * Method:    nGetExtraLibraries
- * Signature: ()Ljava/lang/String;
- */
-JNIEXPORT jstring JNICALL Java_com_sun_media_sound_Platform_nGetExtraLibraries(JNIEnv *env, jclass clss) {
-    return (*env)->NewStringUTF(env, EXTRA_SOUND_JNI_LIBS);
-}
-
-/*
- * Class:     com_sun_media_sound_Platform
- * Method:    nGetLibraryForFeature
- * Signature: (I)I
- */
-JNIEXPORT jint JNICALL Java_com_sun_media_sound_Platform_nGetLibraryForFeature
-  (JNIEnv *env, jclass clazz, jint feature) {
-
-// for every OS
-#if X_PLATFORM == X_WINDOWS
-    switch (feature) {
-    case com_sun_media_sound_Platform_FEATURE_MIDIIO:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_PORTS:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
-        return com_sun_media_sound_Platform_LIB_DSOUND;
-    }
-#endif
-#if (X_PLATFORM == X_SOLARIS)
-    switch (feature) {
-    case com_sun_media_sound_Platform_FEATURE_MIDIIO:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_PORTS:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    }
-#endif
-#if (X_PLATFORM == X_LINUX)
-    switch (feature) {
-    case com_sun_media_sound_Platform_FEATURE_MIDIIO:
-        return com_sun_media_sound_Platform_LIB_ALSA;
-    case com_sun_media_sound_Platform_FEATURE_PORTS:
-        return com_sun_media_sound_Platform_LIB_ALSA;
-    case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
-        return com_sun_media_sound_Platform_LIB_ALSA;
-    }
-#endif
-#if (X_PLATFORM == X_MACOSX)
-    switch (feature) {
-    case com_sun_media_sound_Platform_FEATURE_MIDIIO:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_PORTS:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
-        return com_sun_media_sound_Platform_LIB_MAIN;
-    }
-#endif
-#if (X_PLATFORM == X_BSD)
-    switch (feature) {
-    case com_sun_media_sound_Platform_FEATURE_MIDIIO:
-       return com_sun_media_sound_Platform_LIB_MAIN;
-#ifdef __FreeBSD__
-    case com_sun_media_sound_Platform_FEATURE_PORTS:
-       return com_sun_media_sound_Platform_LIB_ALSA;
-    case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
-       return com_sun_media_sound_Platform_LIB_ALSA;
-#else
-    case com_sun_media_sound_Platform_FEATURE_PORTS:
-       return com_sun_media_sound_Platform_LIB_MAIN;
-    case com_sun_media_sound_Platform_FEATURE_DIRECT_AUDIO:
-       // XXXBSD: When native Direct Audio support is ported change
-       // this back to returning com_sun_media_sound_Platform_LIB_MAIN
-       return 0;
-#endif
-    }
-#endif
-    return 0;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.desktop/solaris/native/libjsound/PLATFORM_API_SolarisOS_PCM.c	Fri Mar 23 11:14:43 2018 -0700
@@ -0,0 +1,626 @@
+/*
+ * Copyright (c) 2003, 2013, 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.
+ */
+
+#define USE_ERROR
+#define USE_TRACE
+
+#include "PLATFORM_API_SolarisOS_Utils.h"
+#include "DirectAudio.h"
+
+#if USE_DAUDIO == TRUE
+
+
+// The default buffer time
+#define DEFAULT_PERIOD_TIME_MILLIS 50
+
+///// implemented functions of DirectAudio.h
+
+INT32 DAUDIO_GetDirectAudioDeviceCount() {
+    return (INT32) getAudioDeviceCount();
+}
+
+
+INT32 DAUDIO_GetDirectAudioDeviceDescription(INT32 mixerIndex,
+                                             DirectAudioDeviceDescription* description) {
+    AudioDeviceDescription desc;
+
+    if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) {
+        description->maxSimulLines = desc.maxSimulLines;
+        strncpy(description->name, desc.name, DAUDIO_STRING_LENGTH-1);
+        description->name[DAUDIO_STRING_LENGTH-1] = 0;
+        strncpy(description->vendor, desc.vendor, DAUDIO_STRING_LENGTH-1);
+        description->vendor[DAUDIO_STRING_LENGTH-1] = 0;
+        strncpy(description->version, desc.version, DAUDIO_STRING_LENGTH-1);
+        description->version[DAUDIO_STRING_LENGTH-1] = 0;
+        /*strncpy(description->description, desc.description, DAUDIO_STRING_LENGTH-1);*/
+        strncpy(description->description, "Solaris Mixer", DAUDIO_STRING_LENGTH-1);
+        description->description[DAUDIO_STRING_LENGTH-1] = 0;
+        return TRUE;
+    }
+    return FALSE;
+
+}
+
+#define MAX_SAMPLE_RATES   20
+
+void DAUDIO_GetFormats(INT32 mixerIndex, INT32 deviceID, int isSource, void* creator) {
+    int fd = -1;
+    AudioDeviceDescription desc;
+    am_sample_rates_t      *sr;
+    /* hardcoded bits and channels */
+    int bits[] = {8, 16};
+    int bitsCount = 2;
+    int channels[] = {1, 2};
+    int channelsCount = 2;
+    /* for querying sample rates */
+    int err;
+    int ch, b, s;
+
+    TRACE2("DAUDIO_GetFormats, mixer %d, isSource=%d\n", mixerIndex, isSource);
+    if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
+        fd = open(desc.pathctl, O_RDONLY);
+    }
+    if (fd < 0) {
+        ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex);
+        return;
+    }
+
+    /* get sample rates */
+    sr = (am_sample_rates_t*) malloc(AUDIO_MIXER_SAMP_RATES_STRUCT_SIZE(MAX_SAMPLE_RATES));
+    if (sr == NULL) {
+        ERROR1("DAUDIO_GetFormats: out of memory for mixer %d\n", (int) mixerIndex);
+        close(fd);
+        return;
+    }
+
+    sr->num_samp_rates = MAX_SAMPLE_RATES;
+    sr->type = isSource?AUDIO_PLAY:AUDIO_RECORD;
+    sr->samp_rates[0] = -2;
+    err = ioctl(fd, AUDIO_MIXER_GET_SAMPLE_RATES, sr);
+    if (err < 0) {
+        ERROR1("  DAUDIO_GetFormats: AUDIO_MIXER_GET_SAMPLE_RATES failed for mixer %d!\n",
+               (int)mixerIndex);
+        ERROR2(" -> num_sample_rates=%d sample_rates[0] = %d\n",
+               (int) sr->num_samp_rates,
+               (int) sr->samp_rates[0]);
+        /* Some Solaris 8 drivers fail for get sample rates!
+         * Do as if we support all sample rates
+         */
+        sr->flags = MIXER_SR_LIMITS;
+    }
+    if ((sr->flags & MIXER_SR_LIMITS)
+        || (sr->num_samp_rates > MAX_SAMPLE_RATES)) {
+#ifdef USE_TRACE
+        if ((sr->flags & MIXER_SR_LIMITS)) {
+            TRACE1("  DAUDIO_GetFormats: floating sample rate allowed by mixer %d\n",
+                   (int)mixerIndex);
+        }
+        if (sr->num_samp_rates > MAX_SAMPLE_RATES) {
+            TRACE2("  DAUDIO_GetFormats: more than %d formats. Use -1 for sample rates mixer %d\n",
+                   MAX_SAMPLE_RATES, (int)mixerIndex);
+        }
+#endif
+        /*
+         * Fake it to have only one sample rate: -1
+         */
+        sr->num_samp_rates = 1;
+        sr->samp_rates[0] = -1;
+    }
+    close(fd);
+
+    for (ch = 0; ch < channelsCount; ch++) {
+        for (b = 0; b < bitsCount; b++) {
+            for (s = 0; s < sr->num_samp_rates; s++) {
+                DAUDIO_AddAudioFormat(creator,
+                                      bits[b], /* significant bits */
+                                      0, /* frameSize: let it be calculated */
+                                      channels[ch],
+                                      (float) ((int) sr->samp_rates[s]),
+                                      DAUDIO_PCM, /* encoding - let's only do PCM */
+                                      (bits[b] > 8)?TRUE:TRUE, /* isSigned */
+#ifdef _LITTLE_ENDIAN
+                                      FALSE /* little endian */
+#else
+                                      (bits[b] > 8)?TRUE:FALSE  /* big endian */
+#endif
+                                      );
+            }
+        }
+    }
+    free(sr);
+}
+
+
+typedef struct {
+    int fd;
+    audio_info_t info;
+    int bufferSizeInBytes;
+    int frameSize; /* storage size in Bytes */
+    /* how many bytes were written or read */
+    INT32 transferedBytes;
+    /* if transferedBytes exceed 32-bit boundary,
+     * it will be reset and positionOffset will receive
+     * the offset
+     */
+    INT64 positionOffset;
+} SolPcmInfo;
+
+
+void* DAUDIO_Open(INT32 mixerIndex, INT32 deviceID, int isSource,
+                  int encoding, float sampleRate, int sampleSizeInBits,
+                  int frameSize, int channels,
+                  int isSigned, int isBigEndian, int bufferSizeInBytes) {
+    int err = 0;
+    int openMode;
+    AudioDeviceDescription desc;
+    SolPcmInfo* info;
+
+    TRACE0("> DAUDIO_Open\n");
+    if (encoding != DAUDIO_PCM) {
+        ERROR1(" DAUDIO_Open: invalid encoding %d\n", (int) encoding);
+        return NULL;
+    }
+    if (channels <= 0) {
+        ERROR1(" DAUDIO_Open: Invalid number of channels=%d!\n", channels);
+        return NULL;
+    }
+
+    info = (SolPcmInfo*) malloc(sizeof(SolPcmInfo));
+    if (!info) {
+        ERROR0("Out of memory\n");
+        return NULL;
+    }
+    memset(info, 0, sizeof(SolPcmInfo));
+    info->frameSize = frameSize;
+    info->fd = -1;
+
+    if (isSource) {
+        openMode = O_WRONLY;
+    } else {
+        openMode = O_RDONLY;
+    }
+
+#ifndef __linux__
+    /* blackdown does not use NONBLOCK */
+    openMode |= O_NONBLOCK;
+#endif
+
+    if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) {
+        info->fd = open(desc.path, openMode);
+    }
+    if (info->fd < 0) {
+        ERROR1("Couldn't open audio device for mixer %d!\n", mixerIndex);
+        free(info);
+        return NULL;
+    }
+    /* set to multiple open */
+    if (ioctl(info->fd, AUDIO_MIXER_MULTIPLE_OPEN, NULL) >= 0) {
+        TRACE1("DAUDIO_Open: %s set to multiple open\n", desc.path);
+    } else {
+        ERROR1("DAUDIO_Open: ioctl AUDIO_MIXER_MULTIPLE_OPEN failed on %s!\n", desc.path);
+    }
+
+    AUDIO_INITINFO(&(info->info));
+    /* need AUDIO_GETINFO ioctl to get this to work on solaris x86  */
+    err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
+
+    /* not valid to call AUDIO_SETINFO ioctl with all the fields from AUDIO_GETINFO. */
+    AUDIO_INITINFO(&(info->info));
+
+    if (isSource) {
+        info->info.play.sample_rate = sampleRate;
+        info->info.play.precision = sampleSizeInBits;
+        info->info.play.channels = channels;
+        info->info.play.encoding = AUDIO_ENCODING_LINEAR;
+        info->info.play.buffer_size = bufferSizeInBytes;
+        info->info.play.pause = 1;
+    } else {
+        info->info.record.sample_rate = sampleRate;
+        info->info.record.precision = sampleSizeInBits;
+        info->info.record.channels = channels;
+        info->info.record.encoding = AUDIO_ENCODING_LINEAR;
+        info->info.record.buffer_size = bufferSizeInBytes;
+        info->info.record.pause = 1;
+    }
+    err = ioctl(info->fd, AUDIO_SETINFO,  &(info->info));
+    if (err < 0) {
+        ERROR0("DAUDIO_Open: could not set info!\n");
+        DAUDIO_Close((void*) info, isSource);
+        return NULL;
+    }
+    DAUDIO_Flush((void*) info, isSource);
+
+    err = ioctl(info->fd, AUDIO_GETINFO, &(info->info));
+    if (err >= 0) {
+        if (isSource) {
+            info->bufferSizeInBytes = info->info.play.buffer_size;
+        } else {
+            info->bufferSizeInBytes = info->info.record.buffer_size;
+        }
+        TRACE2("DAUDIO: buffersize in bytes: requested=%d, got %d\n",
+               (int) bufferSizeInBytes,
+               (int) info->bufferSizeInBytes);
+    } else {