diff --git a/configure b/configure
index 78d305642..a50a36fde 100644
--- a/configure
+++ b/configure
@@ -28,10 +28,6 @@
 # Get an absolute path to this script, since that determines the top-level directory.
 source_path="$(dirname ${0})"
 this_script_dir="$(cd -- "${source_path}" > /dev/null && pwd)"
-if test -z "${this_script_dir}"; then
-  echo "Error: Could not determine location of configure script"
-  exit 1
-fi
 
 # Delegate to wrapper, forcing wrapper to believe $0 is this script by using -c.
 # This trick is needed to get autoconf to co-operate properly.
diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4
index 423654cd5..c9643b872 100644
--- a/make/autoconf/flags-cflags.m4
+++ b/make/autoconf/flags-cflags.m4
@@ -790,11 +790,11 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_CPU_DEP],
     fi
   fi
 
-  if test "x$TOOLCHAIN_TYPE" = xgcc; then
+  #if test "x$TOOLCHAIN_TYPE" = xgcc; then
     # This flag is required since GCC 6 as undefined behavior in OpenJDK code
     # runs afoul of the more aggressive versions of this optimization.
-    $1_TOOLCHAIN_CFLAGS="-fno-lifetime-dse"
-  fi
+  #  $1_TOOLCHAIN_CFLAGS="-fno-lifetime-dse"
+  #fi
 
   if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
     REPRODUCIBLE_CFLAGS="-experimental:deterministic"
diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4
index ff1082873..c01052ea1 100644
--- a/make/autoconf/flags-ldflags.m4
+++ b/make/autoconf/flags-ldflags.m4
@@ -188,7 +188,9 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_CPU_DEP],
         test "x${OPENJDK_$1_CPU}" = xmips64el; then
       $1_CPU_LDFLAGS="${$1_CPU_LDFLAGS} -Wl,--hash-style=sysv"
     else
-      $1_CPU_LDFLAGS="${$1_CPU_LDFLAGS} -Wl,--hash-style=gnu"
+      # Android 5.x does not support GNU hash style
+      # gnu
+      $1_CPU_LDFLAGS="${$1_CPU_LDFLAGS} -Wl,--hash-style=sysv"
     fi
 
   elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
diff --git a/make/autoconf/lib-freetype.m4 b/make/autoconf/lib-freetype.m4
index 8d524c8c8..5399a8bd7 100644
--- a/make/autoconf/lib-freetype.m4
+++ b/make/autoconf/lib-freetype.m4
@@ -105,7 +105,8 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
   FREETYPE_TO_USE=bundled
   if test "x$OPENJDK_TARGET_OS" != "xwindows" && \
       test "x$OPENJDK_TARGET_OS" != "xmacosx" && \
-      test "x$OPENJDK_TARGET_OS" != "xaix"; then
+      test "x$OPENJDK_TARGET_OS" != "xaix" && \
+      test "x$OPENJDK_TARGET_OS" != "xandroid"; then
     FREETYPE_TO_USE=system
   fi
   if test "x$with_freetype" != "x" ; then
diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4
index 5daacdc1c..78c51da67 100644
--- a/make/autoconf/libraries.m4
+++ b/make/autoconf/libraries.m4
@@ -44,6 +44,7 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
   # Check if X11 is needed
   if test "x$OPENJDK_TARGET_OS" = xwindows ||
      test "x$OPENJDK_TARGET_OS" = xmacosx ||
+     test "x$OPENJDK_TARGET_OS" = xandroid ||
      test "x$ENABLE_HEADLESS_ONLY" = xtrue; then
     NEEDS_LIB_X11=false
   else
@@ -52,8 +53,8 @@ AC_DEFUN_ONCE([LIB_DETERMINE_DEPENDENCIES],
   fi
 
   # Check if fontconfig is needed
-  if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx; then
-    # No fontconfig support on windows or macosx
+  if test "x$OPENJDK_TARGET_OS" = xwindows || test "x$OPENJDK_TARGET_OS" = xmacosx || test "x$OPENJDK_TARGET_OS" = xandroid; then
+    # No fontconfig support on windows, macosx or android
     NEEDS_LIB_FONTCONFIG=false
   else
     # All other instances need fontconfig, even if building headless only,
diff --git a/make/autoconf/platform.m4 b/make/autoconf/platform.m4
index 90d5d7956..3a1c80670 100644
--- a/make/autoconf/platform.m4
+++ b/make/autoconf/platform.m4
@@ -202,6 +202,10 @@ AC_DEFUN([PLATFORM_EXTRACT_VARS_FROM_OS],
       VAR_OS=linux
       VAR_OS_TYPE=unix
       ;;
+    *android*)
+      VAR_OS=linux
+      VAR_OS_TYPE=unix
+      ;;
     *darwin*)
       VAR_OS=macosx
       VAR_OS_TYPE=unix
diff --git a/make/autoconf/toolchain.m4 b/make/autoconf/toolchain.m4
index 8a08e86d5..cef968226 100644
--- a/make/autoconf/toolchain.m4
+++ b/make/autoconf/toolchain.m4
@@ -881,11 +881,14 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
 
     PATH="$OLDPATH"
 
-    TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CC, [BuildC])
-    TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CXX, [BuildC++])
-    TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_], [build ])
-    TOOLCHAIN_EXTRACT_LD_VERSION(BUILD_LD, [build linker])
-    TOOLCHAIN_PREPARE_FOR_LD_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_])
+    # xandroid
+    if test "x$OPENJDK_BUILD_OS" != "xlinux"; then
+      TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CC, [BuildC])
+      TOOLCHAIN_EXTRACT_COMPILER_VERSION(BUILD_CXX, [BuildC++])
+      TOOLCHAIN_PREPARE_FOR_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_], [build ])
+      TOOLCHAIN_EXTRACT_LD_VERSION(BUILD_LD, [build linker])
+      TOOLCHAIN_PREPARE_FOR_LD_VERSION_COMPARISONS([BUILD_], [OPENJDK_BUILD_])
+    fi
   else
     # If we are not cross compiling, use the normal target compilers for
     # building the build platform executables.
diff --git a/make/common/Modules.gmk b/make/common/Modules.gmk
index 1ec7bef6f..8612de99b 100644
--- a/make/common/Modules.gmk
+++ b/make/common/Modules.gmk
@@ -71,6 +71,10 @@ GENERATED_SRC_DIRS += \
 TOP_SRC_DIRS += \
     $(TOPDIR)/src \
     #
+ifeq ($(OPENJDK_TARGET_OS), android)
+  SRC_SUBDIRS += linux/classes
+endif
+
 
 SRC_SUBDIRS += $(OPENJDK_TARGET_OS)/classes
 ifneq ($(OPENJDK_TARGET_OS), $(OPENJDK_TARGET_OS_TYPE))
diff --git a/make/common/Utils.gmk b/make/common/Utils.gmk
index b4bb949d3..164ab2202 100644
--- a/make/common/Utils.gmk
+++ b/make/common/Utils.gmk
@@ -193,6 +193,12 @@ MakeDir = \
 isTargetOs = \
   $(strip $(if $(filter $(OPENJDK_TARGET_OS), $1), true, false))
 
+ifeq ($(call isTargetOs, android), true)
+  # PATCH: Since Android is Linux, so Linux specific things are also built for Android.
+  isTargetOs = \
+    $(strip $(if $(filter $(OPENJDK_TARGET_OS), $1), true, $(if $(filter linux, $1), true, false)))
+endif
+
 isTargetOsType = \
   $(strip $(if $(filter $(OPENJDK_TARGET_OS_TYPE), $1), true, false))
 
diff --git a/make/conf/branding.conf b/make/conf/branding.conf
index 912e4f622..27fd26607 100644
--- a/make/conf/branding.conf
+++ b/make/conf/branding.conf
@@ -25,7 +25,7 @@
 
 LAUNCHER_NAME=openjdk
 PRODUCT_NAME=OpenJDK
-PRODUCT_SUFFIX="Runtime Environment"
+PRODUCT_SUFFIX="Android Runtime Environment"
 JDK_RC_PLATFORM_NAME=Platform
 COMPANY_NAME=N/A
 HOTSPOT_VM_DISTRO="OpenJDK"
diff --git a/make/hotspot/lib/JvmOverrideFiles.gmk b/make/hotspot/lib/JvmOverrideFiles.gmk
index 80f358204..75de0d076 100644
--- a/make/hotspot/lib/JvmOverrideFiles.gmk
+++ b/make/hotspot/lib/JvmOverrideFiles.gmk
@@ -61,7 +61,8 @@ ifeq ($(call isTargetOs, linux), true)
       $(OPT_SPEED_SRC) \
       #
 
-  ifeq ($(call isTargetCpu, x86), true)
+  #ifeq ($(call isTargetCpu, x86), true)
+  ifeq (false, true)
     # Performance measurements show that by compiling GC related code, we could
     # significantly reduce the GC pause time on 32 bit Linux/Unix platforms by
     # compiling without the PIC flag (-fPIC on linux).
diff --git a/make/modules/java.desktop/Lib.gmk b/make/modules/java.desktop/Lib.gmk
index 830e0553c..4f37c5a79 100644
--- a/make/modules/java.desktop/Lib.gmk
+++ b/make/modules/java.desktop/Lib.gmk
@@ -79,7 +79,7 @@ ifeq ($(call isTargetOs, aix), false)
       LIBS_windows := advapi32.lib dsound.lib ole32.lib user32.lib winmm.lib, \
   ))
 
-  TARGETS += $(BUILD_LIBJSOUND)
+  # TARGETS += $(BUILD_LIBJSOUND)
 endif
 
 ifeq ($(call isTargetOs, macosx), true)
diff --git a/make/modules/java.instrument/Lib.gmk b/make/modules/java.instrument/Lib.gmk
index 4181cdf81..893e0f418 100644
--- a/make/modules/java.instrument/Lib.gmk
+++ b/make/modules/java.instrument/Lib.gmk
@@ -35,6 +35,9 @@ include LibCommon.gmk
 $(eval $(call SetupJdkLibrary, BUILD_LIBINSTRUMENT, \
     NAME := instrument, \
     OPTIMIZATION := LOW, \
+    EXTRA_SRC := java.base:libtinyiconv, \
+    CXXFLAGS := $(CXXFLAGS_JDKLIB), \
+    LINK_TYPE := C++, \
     CFLAGS := $(ICONV_CFLAGS), \
     CFLAGS_windows := -Dstrcasecmp=stricmp, \
     CFLAGS_debug := -DJPLIS_LOGGING, \
diff --git a/make/modules/jdk.hotspot.agent/Lib.gmk b/make/modules/jdk.hotspot.agent/Lib.gmk
index da02e0dab..e922d0c43 100644
--- a/make/modules/jdk.hotspot.agent/Lib.gmk
+++ b/make/modules/jdk.hotspot.agent/Lib.gmk
@@ -87,6 +87,7 @@ $(eval $(call SetupJdkLibrary, BUILD_LIBSAPROC, \
     LIBS_windows := dbgeng.lib, \
 ))
 
-TARGETS += $(BUILD_LIBSAPROC)
+# Android: libsaproc does not build against bionic (no prstatus_t); skipped like FCL/AngelAuraMC jre25
+# TARGETS += $(BUILD_LIBSAPROC)
 
 ################################################################################
diff --git a/make/modules/jdk.jdwp.agent/Lib.gmk b/make/modules/jdk.jdwp.agent/Lib.gmk
index ce58e145f..90cdec4da 100644
--- a/make/modules/jdk.jdwp.agent/Lib.gmk
+++ b/make/modules/jdk.jdwp.agent/Lib.gmk
@@ -53,6 +53,9 @@ TARGETS += $(BUILD_LIBDT_SOCKET)
 $(eval $(call SetupJdkLibrary, BUILD_LIBJDWP, \
     NAME := jdwp, \
     OPTIMIZATION := LOW, \
+    EXTRA_SRC := java.base:libtinyiconv, \
+    CXXFLAGS := $(CXXFLAGS_JDKLIB), \
+    LINK_TYPE := C++, \
     CFLAGS := -DJDWP_LOGGING $(ICONV_CFLAGS), \
     LDFLAGS := $(ICONV_LDFLAGS), \
     EXTRA_HEADER_DIRS := \
diff --git a/src/hotspot/cpu/arm/icache_arm.cpp b/src/hotspot/cpu/arm/icache_arm.cpp
index 53e982475..fc8fc1cbf 100644
--- a/src/hotspot/cpu/arm/icache_arm.cpp
+++ b/src/hotspot/cpu/arm/icache_arm.cpp
@@ -30,7 +30,7 @@
 
 
 static int icache_flush(address addr, int lines, int magic) {
-  __builtin___clear_cache(addr, addr + (lines << ICache::log2_line_size));
+  __builtin___clear_cache((char*) addr, (char*) (addr + (lines << ICache::log2_line_size)));
   return magic;
 }
 
diff --git a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp
index 3245d07ca..f49054681 100644
--- a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp
+++ b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp
@@ -138,7 +138,7 @@ class ZNUMAConverter {
 static ZNUMAConverter z_numa_converter;
 
 void ZNUMA::pd_initialize() {
-  _enabled = UseNUMA;
+  _enabled = false;
 
   if (UseNUMA) {
     z_numa_converter.initialize();
diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp
index ba48f2b4e..870140c47 100644
--- a/src/hotspot/os/linux/os_linux.cpp
+++ b/src/hotspot/os/linux/os_linux.cpp
@@ -136,10 +136,10 @@
 
 #define MAX_PATH    (2 * K)
 
-#ifdef MUSL_LIBC
+#if defined(MUSL_LIBC) || defined(__ANDROID__)
 // dlvsym is not a part of POSIX
 // and musl libc doesn't implement it.
-static void *dlvsym(void *handle,
+void *dlvsym(void *handle,
                     const char *symbol,
                     const char *version) {
    // load the latest version of symbol
@@ -211,6 +211,8 @@ static malloc_info_func_t g_malloc_info = nullptr;
 // avoid this
 static bool suppress_primordial_thread_resolution = false;
 
+bool read_so_path_from_maps(const char* so_name, char* buf, int buflen);
+
 // utility functions
 
 bool os::is_containerized() {
@@ -536,10 +538,12 @@ bool os::Linux::get_tick_information(CPUPerfTicks* pticks, int which_logical_cpu
 
 #ifndef SYS_gettid
 // i386: 224, amd64: 186
-  #if defined(__i386__)
+  #if defined(__i386__) || defined(__arm__)
     #define SYS_gettid 224
   #elif defined(__amd64__)
     #define SYS_gettid 186
+  #elif defined(__arm64__) || defined(__aarch64__)
+    #define SYS_gettid 178
   #else
     #error "Define SYS_gettid for this architecture"
   #endif
@@ -728,6 +732,7 @@ void os::init_system_properties_values() {
 // detecting pthread library
 
 void os::Linux::libpthread_init() {
+#ifndef __ANDROID__
   // Save glibc and pthread version strings.
 #if !defined(_CS_GNU_LIBC_VERSION) || \
     !defined(_CS_GNU_LIBPTHREAD_VERSION)
@@ -752,6 +757,9 @@ void os::Linux::libpthread_init() {
   confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
   os::Linux::set_libpthread_version(str);
 #endif
+#else
+  os::Linux::set_libpthread_version("NPTL");
+#endif
 }
 
 /////////////////////////////////////////////////////////////////////////////
@@ -1551,7 +1559,13 @@ int os::current_process_id() {
 
 // This must be hard coded because it's the system's temporary
 // directory not the java application's temp directory, ala java.io.tmpdir.
-const char* os::get_temp_directory() { return "/tmp"; }
+const char* os::get_temp_directory() {
+#ifndef __ANDROID__
+  return "/tmp";
+#else
+  return "/data/tmp";
+#endif
+}
 
 // check if addr is inside libjvm.so
 bool os::address_is_in_vm(address addr) {
@@ -1626,6 +1640,30 @@ bool os::dll_address_to_library_name(address addr, char* buf,
   return false;
 }
 
+bool read_so_path_from_maps(const char* so_name, char* buf, int buflen) {
+  FILE *fp = fopen("/proc/self/maps", "r");
+  assert(fp, "Failed to open /proc/self/maps");
+  if (!fp) {
+    return false;
+  }
+
+  char maps_buffer[2048];
+  while (fgets(maps_buffer, 2048, fp) != NULL) {
+    if (strstr(maps_buffer, so_name) == NULL) {
+      continue;
+    }
+
+    char *so_path = strchr(maps_buffer, '/');
+    so_path[strlen(so_path) - 1] = '\0'; // Cut trailing \n
+    jio_snprintf(buf, buflen, "%s", so_path);
+    fclose(fp);
+    return true;
+  }
+
+  fclose(fp);
+  return false;
+}
+
 // Remember the stack's state. The Linux dynamic linker will change
 // the stack to 'executable' at most once, so we must safepoint only once.
 bool os::Linux::_stack_is_executable = false;
@@ -2025,6 +2063,7 @@ void * os::Linux::dll_load_in_vmthread(const char *filename, char *ebuf,
 }
 
 const char* os::Linux::dll_path(void* lib) {
+#ifdef RTLD_DI_LINKMAP
   struct link_map *lmap;
   const char* l_path = nullptr;
   assert(lib != nullptr, "dll_path parameter must not be null");
@@ -2034,6 +2073,9 @@ const char* os::Linux::dll_path(void* lib) {
     l_path = lmap->l_name;
   }
   return l_path;
+#else
+  return NULL;
+#endif
 }
 
 static unsigned count_newlines(const char* s) {
@@ -3164,7 +3206,8 @@ void os::Linux::sched_getcpu_init() {
   }
 
   if (sched_getcpu() == -1) {
-    vm_exit_during_initialization("getcpu(2) system call not supported by kernel");
+    // vm_exit_during_initialization
+    warning("getcpu(2) system call not supported by kernel");
   }
 }
 
@@ -3195,14 +3238,8 @@ static bool numa_syscall_check() {
   // Especially in dockers, get_mempolicy is not allowed with the default configuration. So it's necessary
   // to check whether the syscalls are available. Currently, only get_mempolicy is checked since checking
   // others like mbind would cause unexpected side effects.
-#ifdef SYS_get_mempolicy
-  int dummy = 0;
-  if (syscall(SYS_get_mempolicy, &dummy, nullptr, 0, (void*)&dummy, 3) == -1) {
-    return false;
-  }
-#endif
 
-  return true;
+  return false;
 }
 
 bool os::Linux::libnuma_init() {
@@ -5109,7 +5146,46 @@ bool os::is_thread_cpu_time_supported() {
 // Linux doesn't yet have a (official) notion of processor sets,
 // so just return the system wide load average.
 int os::loadavg(double loadavg[], int nelem) {
-  return ::getloadavg(loadavg, nelem);
+#ifndef __ANDROID__
+   return ::getloadavg(loadavg, nelem);
+#else
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+  if (nelem < 0) return -1;
+  if (nelem > 3) nelem = 3;
+  struct sysinfo si;
+  if (sysinfo(&si) == -1) return -1;
+  for (int i = 0; i < nelem; ++i) {
+    loadavg[i] = static_cast<double>(si.loads[i]) / static_cast<double>(1 << SI_LOAD_SHIFT);
+  }
+  return nelem;
+#endif
 }
 
 // Get the default path to the core file
diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp
index c0e863ed2..cff4b7d4c 100644
--- a/src/hotspot/os/linux/os_perf_linux.cpp
+++ b/src/hotspot/os/linux/os_perf_linux.cpp
@@ -36,7 +36,18 @@
 #include <dlfcn.h>
 #include <errno.h>
 #include <fcntl.h>
+#ifndef __ANDROID__
 #include <ifaddrs.h>
+#else
+#include <sys/cdefs.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <linux/if_packet.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <net/if.h>
+#include <stdint.h>
+#endif
 #include <limits.h>
 #include <pthread.h>
 #include <stdarg.h>
@@ -47,6 +58,299 @@
 #include <sys/types.h>
 #include <unistd.h>
 
+#ifdef __ANDROID__
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+__BEGIN_DECLS
+
+/**
+ * Returned by getifaddrs() and freed by freeifaddrs().
+ */
+struct ifaddrs {
+  /** Pointer to the next element in the linked list. */
+  struct ifaddrs* ifa_next;
+
+  /** Interface name. */
+  char* ifa_name;
+
+  /** Interface flags (like `SIOCGIFFLAGS`). */
+  unsigned int ifa_flags;
+
+  /** Interface address. */
+  struct sockaddr* ifa_addr;
+
+  /** Interface netmask. */
+  struct sockaddr* ifa_netmask;
+
+  union {
+    /** Interface broadcast address (if IFF_BROADCAST is set). */
+    struct sockaddr* ifu_broadaddr;
+
+    /** Interface destination address (if IFF_POINTOPOINT is set). */
+    struct sockaddr* ifu_dstaddr;
+  } ifa_ifu;
+
+  /** Unused. */
+  void* ifa_data;
+};
+
+/** Synonym for `ifa_ifu.ifu_broadaddr` in `struct ifaddrs`. */
+#define ifa_broadaddr ifa_ifu.ifu_broadaddr
+
+/** Synonym for `ifa_ifu.ifu_dstaddr` in `struct ifaddrs`. */
+#define ifa_dstaddr ifa_ifu.ifu_dstaddr
+
+/**
+ * [getifaddrs(3)](http://man7.org/linux/man-pages/man3/getifaddrs.3.html) creates a linked list
+ * of `struct ifaddrs`. The list must be freed by freeifaddrs().
+ *
+ * Returns 0 and stores the list in `*__list_ptr` on success,
+ * and returns -1 and sets `errno` on failure.
+ *
+ * Available since API level 24.
+ */
+int getifaddrs(struct ifaddrs** __list_ptr); // __INTRODUCED_IN(24);
+
+/**
+ * [freeifaddrs(3)](http://man7.org/linux/man-pages/man3/freeifaddrs.3.html) frees a linked list
+ * of `struct ifaddrs` returned by getifaddrs().
+ *
+ * Available since API level 24.
+ */
+void freeifaddrs(struct ifaddrs* __ptr); // __INTRODUCED_IN(24);
+
+__END_DECLS
+
+#define nullptr 0
+
+// The public ifaddrs struct is full of pointers. Rather than track several
+// different allocations, we use a maximally-sized structure with the public
+// part at offset 0, and pointers into its hidden tail.
+struct ifaddrs_storage {
+  // Must come first, so that `ifaddrs_storage` is-a `ifaddrs`.
+  ifaddrs ifa;
+  // The interface index, so we can match RTM_NEWADDR messages with
+  // earlier RTM_NEWLINK messages (to copy the interface flags).
+  int interface_index;
+  // Storage for the pointers in `ifa`.
+  sockaddr_storage addr;
+  sockaddr_storage netmask;
+  sockaddr_storage ifa_ifu;
+  char name[IFNAMSIZ + 1];
+  // Netlink gives us the address family in the header, and the
+  // sockaddr_in or sockaddr_in6 bytes as the payload. We need to
+  // stitch the two bits together into the sockaddr that's part of
+  // our portable interface.
+  void SetAddress(int family, const void* data, size_t byteCount) {
+      addr.ss_family = family;
+      memcpy(SockaddrBytes(family, &addr), data, byteCount);
+      ifa.ifa_addr = reinterpret_cast<sockaddr*>(&addr);
+  }
+  void SetBroadcastAddress(int family, const void* data, size_t byteCount) {
+      ifa_ifu.ss_family = family;
+      memcpy(SockaddrBytes(family, &ifa_ifu), data, byteCount);
+      ifa.ifa_dstaddr = reinterpret_cast<sockaddr*>(&ifa_ifu);
+  }
+  // Netlink gives us the prefix length as a bit count. We need to turn
+  // that into a BSD-compatible netmask represented by a sockaddr*.
+  void SetNetmask(int family, size_t prefix_length) {
+      // ...and work out the netmask from the prefix length.
+      netmask.ss_family = family;
+      uint8_t* dst = SockaddrBytes(family, &netmask);
+      memset(dst, 0xff, prefix_length / 8);
+      if ((prefix_length % 8) != 0) {
+        dst[prefix_length/8] = (0xff << (8 - (prefix_length % 8)));
+      }
+      ifa.ifa_netmask = reinterpret_cast<sockaddr*>(&netmask);
+  }
+  void SetPacketAttributes(int ifindex, unsigned short hatype, unsigned char halen) {
+    sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(&addr);
+    sll->sll_ifindex = ifindex;
+    sll->sll_hatype = hatype;
+    sll->sll_halen = halen;
+  }
+ private:
+  // Returns a pointer to the first byte in the address data (which is
+  // stored in network byte order).
+  uint8_t* SockaddrBytes(int family, sockaddr_storage* ss) {
+    if (family == AF_INET) {
+      sockaddr_in* ss4 = reinterpret_cast<sockaddr_in*>(ss);
+      return reinterpret_cast<uint8_t*>(&ss4->sin_addr);
+    } else if (family == AF_INET6) {
+      sockaddr_in6* ss6 = reinterpret_cast<sockaddr_in6*>(ss);
+      return reinterpret_cast<uint8_t*>(&ss6->sin6_addr);
+    } else if (family == AF_PACKET) {
+      sockaddr_ll* sll = reinterpret_cast<sockaddr_ll*>(ss);
+      return reinterpret_cast<uint8_t*>(&sll->sll_addr);
+    }
+    return nullptr;
+  }
+};
+ifaddrs_storage* new_ifaddrs_storage(ifaddrs** list) {
+  ifaddrs_storage *storage;
+  memset(storage, 0, sizeof(*storage));
+  // push_front onto `list`.
+  storage->ifa.ifa_next = *list;
+  *list = reinterpret_cast<ifaddrs*>(storage);
+  return storage;
+}
+#if !defined(__clang__)
+// GCC gets confused by NLMSG_DATA and doesn't realize that the old-style
+// cast is from a system header and should be ignored.
+#pragma GCC diagnostic ignored "-Wold-style-cast"
+#endif
+static void __handle_netlink_response(ifaddrs** out, nlmsghdr* hdr) {
+  if (hdr->nlmsg_type == RTM_NEWLINK) {
+    ifinfomsg* ifi = reinterpret_cast<ifinfomsg*>(NLMSG_DATA(hdr));
+    // Create a new ifaddr entry, and set the interface index and flags.
+    ifaddrs_storage* new_addr = new_ifaddrs_storage(out);
+    new_addr->interface_index = ifi->ifi_index;
+    new_addr->ifa.ifa_flags = ifi->ifi_flags;
+    // Go through the various bits of information and find the name.
+    rtattr* rta = IFLA_RTA(ifi);
+    size_t rta_len = IFLA_PAYLOAD(hdr);
+    while (RTA_OK(rta, rta_len)) {
+      if (rta->rta_type == IFLA_ADDRESS) {
+          if (RTA_PAYLOAD(rta) < sizeof(new_addr->addr)) {
+            new_addr->SetAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta));
+            new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta));
+          }
+      } else if (rta->rta_type == IFLA_BROADCAST) {
+          if (RTA_PAYLOAD(rta) < sizeof(new_addr->ifa_ifu)) {
+            new_addr->SetBroadcastAddress(AF_PACKET, RTA_DATA(rta), RTA_PAYLOAD(rta));
+            new_addr->SetPacketAttributes(ifi->ifi_index, ifi->ifi_type, RTA_PAYLOAD(rta));
+          }
+      } else if (rta->rta_type == IFLA_IFNAME) {
+          if (RTA_PAYLOAD(rta) < sizeof(new_addr->name)) {
+            memcpy(new_addr->name, RTA_DATA(rta), RTA_PAYLOAD(rta));
+            new_addr->ifa.ifa_name = new_addr->name;
+          }
+      }
+      rta = RTA_NEXT(rta, rta_len);
+    }
+  } else if (hdr->nlmsg_type == RTM_NEWADDR) {
+    ifaddrmsg* msg = reinterpret_cast<ifaddrmsg*>(NLMSG_DATA(hdr));
+    // We should already know about this from an RTM_NEWLINK message.
+    const ifaddrs_storage* addr = reinterpret_cast<const ifaddrs_storage*>(*out);
+    while (addr != nullptr && addr->interface_index != static_cast<int>(msg->ifa_index)) {
+      addr = reinterpret_cast<const ifaddrs_storage*>(addr->ifa.ifa_next);
+    }
+    // If this is an unknown interface, ignore whatever we're being told about it.
+    if (addr == nullptr) return;
+    // Create a new ifaddr entry and copy what we already know.
+    ifaddrs_storage* new_addr = new_ifaddrs_storage(out);
+    // We can just copy the name rather than look for IFA_LABEL.
+    strcpy(new_addr->name, addr->name);
+    new_addr->ifa.ifa_name = new_addr->name;
+    new_addr->ifa.ifa_flags = addr->ifa.ifa_flags;
+    new_addr->interface_index = addr->interface_index;
+    // Go through the various bits of information and find the address
+    // and any broadcast/destination address.
+    rtattr* rta = IFA_RTA(msg);
+    size_t rta_len = IFA_PAYLOAD(hdr);
+    while (RTA_OK(rta, rta_len)) {
+      if (rta->rta_type == IFA_ADDRESS) {
+        if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
+          new_addr->SetAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
+          new_addr->SetNetmask(msg->ifa_family, msg->ifa_prefixlen);
+        }
+      } else if (rta->rta_type == IFA_BROADCAST) {
+        if (msg->ifa_family == AF_INET || msg->ifa_family == AF_INET6) {
+          new_addr->SetBroadcastAddress(msg->ifa_family, RTA_DATA(rta), RTA_PAYLOAD(rta));
+        }
+      }
+      rta = RTA_NEXT(rta, rta_len);
+    }
+  }
+}
+static bool __send_netlink_request(int fd, int type) {
+  struct NetlinkMessage {
+    nlmsghdr hdr;
+    rtgenmsg msg;
+  } request;
+  memset(&request, 0, sizeof(request));
+  request.hdr.nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST;
+  request.hdr.nlmsg_type = type;
+  request.hdr.nlmsg_len = sizeof(request);
+  request.msg.rtgen_family = AF_UNSPEC; // All families.
+  return (TEMP_FAILURE_RETRY(send(fd, &request, sizeof(request), 0)) == sizeof(request));
+}
+static bool __read_netlink_responses(int fd, ifaddrs** out, char* buf, size_t buf_len) {
+  ssize_t bytes_read;
+  // Read through all the responses, handing interesting ones to __handle_netlink_response.
+  while ((bytes_read = TEMP_FAILURE_RETRY(recv(fd, buf, buf_len, 0))) > 0) {
+    nlmsghdr* hdr = reinterpret_cast<nlmsghdr*>(buf);
+    for (; NLMSG_OK(hdr, static_cast<size_t>(bytes_read)); hdr = NLMSG_NEXT(hdr, bytes_read)) {
+      if (hdr->nlmsg_type == NLMSG_DONE) return true;
+      if (hdr->nlmsg_type == NLMSG_ERROR) return false;
+      __handle_netlink_response(out, hdr);
+    }
+  }
+  // We only get here if recv fails before we see a NLMSG_DONE.
+  return false;
+}
+int getifaddrs(ifaddrs** out) {
+  // Make cleanup easy.
+  *out = nullptr;
+  // The kernel keeps packets under 8KiB (NLMSG_GOODSIZE),
+  // but that's a bit too large to go on the stack.
+  size_t buf_len = 8192;
+  char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal);
+  if (buf == nullptr) return -1;
+  // Open the netlink socket and ask for all the links and addresses.
+  int fd = socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
+  bool okay = fd != -1 &&
+      __send_netlink_request(fd, RTM_GETLINK) && __read_netlink_responses(fd, out, buf, buf_len) &&
+      __send_netlink_request(fd, RTM_GETADDR) && __read_netlink_responses(fd, out, buf, buf_len);
+  if (!okay) {
+    freeifaddrs(*out);
+    // Ensure that callers crash if they forget to check for success.
+    *out = nullptr;
+  }
+  {
+    int saved_errno = errno;
+    close(fd);
+    FREE_C_HEAP_ARRAY(buf);
+    errno = saved_errno;
+  }
+  return okay ? 0 : -1;
+}
+void freeifaddrs(ifaddrs* list) {
+  while (list != nullptr) {
+    ifaddrs* current = list;
+    list = list->ifa_next;
+    free(current);
+  }
+}
+#endif
+
+
 /**
    /proc/[number]/stat
               Status information about the process.  This is used by ps(1).  It is defined in /usr/src/linux/fs/proc/array.c.
diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp
index 1eee76b46..cb5dd2a22 100644
--- a/src/hotspot/os/posix/os_posix.cpp
+++ b/src/hotspot/os/posix/os_posix.cpp
@@ -85,7 +85,9 @@
 #include <sys/wait.h>
 #include <time.h>
 #include <unistd.h>
+#ifndef __ANDROID__
 #include <utmpx.h>
+#endif
 
 #ifdef __APPLE__
   #include <crt_externs.h>
@@ -566,6 +568,7 @@ void os::Posix::print_load_average(outputStream* st) {
 // unfortunately it does not work on macOS and Linux because the utx chain has no entry
 // for reboot at least on my test machines
 void os::Posix::print_uptime_info(outputStream* st) {
+#ifndef __ANDROID__
   int bootsec = -1;
   time_t currsec = time(nullptr);
   struct utmpx* ent;
@@ -580,6 +583,7 @@ void os::Posix::print_uptime_info(outputStream* st) {
   if (bootsec != -1) {
     os::print_dhm(st, "OS uptime:", currsec-bootsec);
   }
+#endif
 }
 
 static void print_rlimit(outputStream* st, const char* msg,
@@ -1149,6 +1153,25 @@ void os::jvm_path(char *buf, jint buflen) {
   }
   fname = dli_fname;
 #endif // AIX
+#ifdef __ANDROID__
+  if (fname[0] == '\0') {
+    return;
+  }
+  if (strchr(fname, '/') == nullptr) {
+    extern bool read_so_path_from_maps(const char* so_name, char* buf, int buflen);
+    bool ok = read_so_path_from_maps(fname, buf, buflen);
+    assert(ok, "unable to turn relative libjvm.so path into absolute");
+    if (ok) {
+      strncpy(saved_jvm_path, buf, MAXPATHLEN);
+      saved_jvm_path[MAXPATHLEN - 1] = '\0';
+    }
+    return;
+  }
+  snprintf(buf, buflen, "%s", fname);
+  strncpy(saved_jvm_path, buf, MAXPATHLEN);
+  saved_jvm_path[MAXPATHLEN - 1] = '\0';
+  return;
+#endif // __ANDROID__
   char* rp = nullptr;
   if (fname[0] != '\0') {
     rp = os::realpath(fname, buf, buflen);
@@ -2152,11 +2175,31 @@ int os::fork_and_exec(const char* cmd) {
   const char* argv[4] = {"sh", "-c", cmd, nullptr};
   pid_t pid = -1;
   char** env = os::get_environ();
+#ifndef __ANDROID__
   // Note: cast is needed because posix_spawn() requires - for compatibility with ancient
   // C-code - a non-const argv/envp pointer array. But it is fine to hand in literal
   // strings and just cast the constness away. See also ProcessImpl_md.c.
   int rc = ::posix_spawn(&pid, "/bin/sh", nullptr, nullptr, (char**) argv, env);
   if (rc == 0) {
+#else
+  pid = ::fork();
+
+  if (pid < 0) {
+    // fork failed
+    return -1;
+
+  } else if (pid == 0) {
+    // child process
+
+    ::execve("/bin/sh", (char* const*)argv, env);
+
+    // execve failed
+    ::_exit(-1);
+
+  } else  {
+    // copied from J2SE ..._waitForProcessExit() in UNIXProcess_md.c; we don't
+    // care about the actual exit code, for now.
+#endif
     int status;
     // Wait for the child process to exit.  This returns immediately if
     // the child has already exited. */
@@ -2181,9 +2224,11 @@ int os::fork_and_exec(const char* cmd) {
       // Unknown exit code; pass it through
       return status;
     }
+#ifndef __ANDROID__
   } else {
     // Don't log, we are inside error handling
     return -1;
+#endif
   }
 }
 
diff --git a/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp
index c6e012ecf..d4f956756 100644
--- a/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp
+++ b/src/hotspot/os_cpu/linux_aarch64/javaThread_linux_aarch64.hpp
@@ -47,6 +47,8 @@
   bool pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava);
 public:
 
-  static Thread *aarch64_get_thread_helper();
+  static Thread *aarch64_get_thread_helper() {
+    return Thread::current();
+  }
 
 #endif // OS_CPU_LINUX_AARCH64_JAVATHREAD_LINUX_AARCH64_HPP
diff --git a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
index 33be49019..7f6ad8be5 100644
--- a/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
+++ b/src/hotspot/os_cpu/linux_aarch64/threadLS_linux_aarch64.S
@@ -22,6 +22,7 @@
 
 #include "defs.S.inc"
 
+#ifndef __ANDROID__
         // JavaThread::aarch64_get_thread_helper()
         //
         // Return the current thread pointer in x0.
@@ -44,7 +45,7 @@ DECLARE_FUNC(_ZN10JavaThread25aarch64_get_thread_helperEv):
         ret
 
         .size _ZN10JavaThread25aarch64_get_thread_helperEv, .-_ZN10JavaThread25aarch64_get_thread_helperEv
-
+#endif
 /* Emit .note.gnu.property section in case of PAC or BTI being enabled.
  * For more details see "ELF for the Arm(R) 64-bit Architecture (AArch64)".
  * https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst
diff --git a/src/hotspot/os_cpu/linux_arm/fpu_control.h b/src/hotspot/os_cpu/linux_arm/fpu_control.h
new file mode 100644
index 000000000..745243d62
--- /dev/null
+++ b/src/hotspot/os_cpu/linux_arm/fpu_control.h
@@ -0,0 +1,59 @@
+/* FPU control word definitions.  ARM VFP version.
+   Copyright (C) 2004-2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+   The GNU C Library 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
+   Lesser General Public License for more details.
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+#ifndef _FPU_CONTROL_H
+#define _FPU_CONTROL_H
+#if !(defined(_LIBC) && !defined(_LIBC_TEST)) && defined(__SOFTFP__)
+#define _FPU_RESERVED 0xffffffff
+#define _FPU_DEFAULT  0x00000000
+typedef unsigned int fpu_control_t;
+#define _FPU_GETCW(cw) (cw) = 0
+#define _FPU_SETCW(cw) (void) (cw)
+extern fpu_control_t __fpu_control;
+#else
+/* masking of interrupts */
+#define _FPU_MASK_IM        0x00000100        /* invalid operation */
+#define _FPU_MASK_ZM        0x00000200        /* divide by zero */
+#define _FPU_MASK_OM        0x00000400        /* overflow */
+#define _FPU_MASK_UM        0x00000800        /* underflow */
+#define _FPU_MASK_PM        0x00001000        /* inexact */
+#define _FPU_MASK_NZCV        0xf0000000        /* NZCV flags */
+#define _FPU_MASK_RM        0x00c00000        /* rounding mode */
+#define _FPU_MASK_EXCEPT 0x00001f1f        /* all exception flags */
+/* Some bits in the FPSCR are not yet defined.  They must be preserved when
+   modifying the contents.  */
+#define _FPU_RESERVED        0x00086060
+#define _FPU_DEFAULT    0x00000000
+/* Default + exceptions enabled.  */
+#define _FPU_IEEE        (_FPU_DEFAULT | 0x00001f00)
+/* Type of the control word.  */
+typedef unsigned int fpu_control_t;
+/* Macros for accessing the hardware control word.  */
+#ifdef __SOFTFP__
+/* This is fmrx %0, fpscr.  */
+# define _FPU_GETCW(cw) \
+  __asm__ __volatile__ ("mrc p10, 7, %0, cr1, cr0, 0" : "=r" (cw))
+/* This is fmxr fpscr, %0.  */
+# define _FPU_SETCW(cw) \
+  __asm__ __volatile__ ("mcr p10, 7, %0, cr1, cr0, 0" : : "r" (cw))
+#else
+# define _FPU_GETCW(cw) \
+  __asm__ __volatile__ ("vmrs %0, fpscr" : "=r" (cw))
+# define _FPU_SETCW(cw) \
+  __asm__ __volatile__ ("vmsr fpscr, %0" : : "r" (cw))
+#endif
+/* Default control word set at startup.  */
+extern fpu_control_t __fpu_control;
+#endif /* __SOFTFP__ */
+#endif /* _FPU_CONTROL_H */
diff --git a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
index a866858da..db3a44c71 100644
--- a/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
+++ b/src/hotspot/os_cpu/linux_arm/linux_arm_32.S
@@ -66,7 +66,7 @@ dw_f2b_loop_32:
         stmia to!, {r3 - r9, ip}
         bgt     dw_f2b_loop_32
 dw_f2b_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     disjoint_words_finish
         cmp     r2, #16
         blt	disjoint_words_small
@@ -114,7 +114,7 @@ cw_f2b_loop_32:
         stmia to!, {r3 - r9, ip}
         bgt     cw_f2b_loop_32
 cw_f2b_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     conjoint_words_finish
         cmp     r2, #16
         blt	conjoint_words_small
@@ -147,7 +147,7 @@ cw_b2f_loop_32:
         stmdb to!, {r3-r9,ip}
         bgt     cw_b2f_loop_32
 cw_b2f_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     conjoint_words_finish
         cmp     r2, #16
         blt	cw_b2f_copy_small
@@ -199,7 +199,7 @@ cs_f2b_loop_32:
         stmia to!, {r3 - r9, ip}
         bgt     cs_f2b_loop_32
 cs_f2b_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     conjoint_shorts_finish
         movs    r6, r2, lsr #3
         .align 3
@@ -215,11 +215,11 @@ cs_f2b_4:
         beq     conjoint_shorts_finish
         cmp     r2, #4
         ldrh    r3, [from], #2
-        ldrgeh  r4, [from], #2
-        ldrgth  r5, [from], #2
+        ldrhge  r4, [from], #2
+        ldrhgt  r5, [from], #2
         strh    r3, [to], #2
-        strgeh  r4, [to], #2
-        strgth  r5, [to], #2
+        strhge  r4, [to], #2
+        strhgt  r5, [to], #2
         b       conjoint_shorts_finish
 
         # Destination not aligned
@@ -277,11 +277,11 @@ cs_f2b_4_u:
         beq     conjoint_shorts_finish
         cmp     r2, #4
         ldrh    r3, [from], #2
-        ldrgeh  r4, [from], #2
-        ldrgth  r5, [from], #2
+        ldrhge  r4, [from], #2
+        ldrhgt  r5, [from], #2
         strh    r3, [to], #2
-        strgeh  r4, [to], #2
-        strgth  r5, [to], #2
+        strhge  r4, [to], #2
+        strhgt  r5, [to], #2
         b       conjoint_shorts_finish
 
         # Src and dest overlap, copy in a descending order
@@ -304,7 +304,7 @@ cs_b2f_loop_32:
         stmdb to!, {r3-r9,ip}
         bgt     cs_b2f_loop_32
 cs_b2f_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     conjoint_shorts_finish
         cmp     r2, #24
         blt     cs_b2f_16
@@ -330,11 +330,11 @@ cs_b2f_8:
 cs_b2f_all_copy:
         cmp     r2, #4
         ldrh    r3, [from, #-2]!
-        ldrgeh  r4, [from, #-2]!
-        ldrgth  r5, [from, #-2]!
+        ldrhge  r4, [from, #-2]!
+        ldrhgt  r5, [from, #-2]!
         strh    r3, [to, #-2]!
-        strgeh  r4, [to, #-2]!
-        strgth  r5, [to, #-2]!
+        strhge  r4, [to, #-2]!
+        strhgt  r5, [to, #-2]!
         b       conjoint_shorts_finish
 
         # Destination not aligned
@@ -369,7 +369,7 @@ cs_b2f_16_loop_u:
         bgt     cs_b2f_16_loop_u
         beq     conjoint_shorts_finish
 cs_b2f_16_loop_u_finished:
-        addlts  r2, #16
+        addslt  r2, #16
         ldr     r3, [from]
         cmp     r2, #10
         blt     cs_b2f_2_u_loop
@@ -432,7 +432,7 @@ cl_f2b_loop_32:
         stmia to!, {r3 - r9, ip}
         bgt     cl_f2b_loop_32
 cl_f2b_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     conjoint_longs_finish
 conjoint_longs_small:
         cmp     r2, #16
@@ -465,7 +465,7 @@ cl_b2f_loop_32:
         stmdb 	to!, {r3 - r9, ip}
         bgt     cl_b2f_loop_32
 cl_b2f_loop_32_finish:
-        addlts  r2, #32
+        addslt  r2, #32
         beq     conjoint_longs_finish
         cmp     r2, #16
         blt	cl_b2f_copy_8
diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
index 41a4dbea3..1b77c0cb9 100644
--- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
+++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp
@@ -70,7 +70,11 @@
 # include <pwd.h>
 # include <poll.h>
 # include <ucontext.h>
+#ifndef __ANDROID__
 # include <fpu_control.h>
+#else
+# include "fpu_control.h" //include the local header
+#endif
 # include <asm/ptrace.h>
 
 #define SPELL_REG_SP  "sp"
@@ -88,8 +92,14 @@ enum {
 #endif
 
 address os::current_stack_pointer() {
+#if defined(__clang__) || defined(__llvm__)
+  void *sp;
+  __asm__("mov %0, " SPELL_REG_SP : "=r"(sp));
+  return (address) sp;
+#else
   register address sp __asm__ (SPELL_REG_SP);
   return sp;
+#endif
 }
 
 char* os::non_memory_address_word() {
@@ -444,8 +454,8 @@ void os::setup_fpu() {
 #if !defined(__SOFTFP__) && defined(__VFP_FP__)
   // Turn on IEEE-754 compliant VFP mode
   __asm__ volatile (
-    "mov %%r0, #0;"
-    "fmxr fpscr, %%r0"
+    "mov r0, #0;"
+    "fmxr fpscr, r0"
     : /* no output */ : /* no input */ : "r0"
   );
 #endif
diff --git a/src/hotspot/os_cpu/linux_x86/fpu_control.h b/src/hotspot/os_cpu/linux_x86/fpu_control.h
new file mode 100644
index 000000000..605302c09
--- /dev/null
+++ b/src/hotspot/os_cpu/linux_x86/fpu_control.h
@@ -0,0 +1,109 @@
+/* FPU control word bits.  x86 version.
+   Copyright (C) 1993-2012 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Olaf Flebbe.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _FPU_CONTROL_H
+#define _FPU_CONTROL_H	1
+
+/* Note that this file sets on x86-64 only the x87 FPU, it does not
+   touch the SSE unit.  */
+
+/* Here is the dirty part. Set up your 387 through the control word
+ * (cw) register.
+ *
+ *     15-13    12  11-10  9-8     7-6     5    4    3    2    1    0
+ * | reserved | IC | RC  | PC | reserved | PM | UM | OM | ZM | DM | IM
+ *
+ * IM: Invalid operation mask
+ * DM: Denormalized operand mask
+ * ZM: Zero-divide mask
+ * OM: Overflow mask
+ * UM: Underflow mask
+ * PM: Precision (inexact result) mask
+ *
+ * Mask bit is 1 means no interrupt.
+ *
+ * PC: Precision control
+ * 11 - round to extended precision
+ * 10 - round to double precision
+ * 00 - round to single precision
+ *
+ * RC: Rounding control
+ * 00 - rounding to nearest
+ * 01 - rounding down (toward - infinity)
+ * 10 - rounding up (toward + infinity)
+ * 11 - rounding toward zero
+ *
+ * IC: Infinity control
+ * That is for 8087 and 80287 only.
+ *
+ * The hardware default is 0x037f which we use.
+ */
+
+#include <features.h>
+
+/* masking of interrupts */
+#define _FPU_MASK_IM  0x01
+#define _FPU_MASK_DM  0x02
+#define _FPU_MASK_ZM  0x04
+#define _FPU_MASK_OM  0x08
+#define _FPU_MASK_UM  0x10
+#define _FPU_MASK_PM  0x20
+
+/* precision control */
+#define _FPU_EXTENDED 0x300	/* libm requires double extended precision.  */
+#define _FPU_DOUBLE   0x200
+#define _FPU_SINGLE   0x0
+
+/* rounding control */
+#define _FPU_RC_NEAREST 0x0    /* RECOMMENDED */
+#define _FPU_RC_DOWN    0x400
+#define _FPU_RC_UP      0x800
+#define _FPU_RC_ZERO    0xC00
+
+#define _FPU_RESERVED 0xF0C0  /* Reserved bits in cw */
+
+
+/* The fdlibm code requires strict IEEE double precision arithmetic,
+   and no interrupts for exceptions, rounding to nearest.  */
+
+#define _FPU_DEFAULT  0x037f
+
+/* IEEE:  same as above.  */
+#define _FPU_IEEE     0x037f
+
+/* Type of the control word.  */
+typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__HI__)));
+
+/* Macros for accessing the hardware control word.  "*&" is used to
+   work around a bug in older versions of GCC.  __volatile__ is used
+   to support combination of writing the control register and reading
+   it back.  Without __volatile__, the old value may be used for reading
+   back under compiler optimization.
+
+   Note that the use of these macros is not sufficient anymore with
+   recent hardware nor on x86-64.  Some floating point operations are
+   executed in the SSE/SSE2 engines which have their own control and
+   status register.  */
+#define _FPU_GETCW(cw) __asm__ __volatile__ ("fnstcw %0" : "=m" (*&cw))
+#define _FPU_SETCW(cw) __asm__ __volatile__ ("fldcw %0" : : "m" (*&cw))
+
+/* Default control word set at startup.  */
+extern fpu_control_t __fpu_control;
+
+#endif	/* fpu_control.h */
diff --git a/src/hotspot/share/utilities/compilerWarnings.hpp b/src/hotspot/share/utilities/compilerWarnings.hpp
index 3a2a94164..48ca109c6 100644
--- a/src/hotspot/share/utilities/compilerWarnings.hpp
+++ b/src/hotspot/share/utilities/compilerWarnings.hpp
@@ -128,7 +128,12 @@
 
 // Both Linux and AIX C libraries declare functions noexcept.
 // Neither BSD nor Windows C libraries declare functions noexcept.
+#ifdef __ANDROID__
+// Android bionic headers do not declare C library functions noexcept.
+#define FORBIDDEN_FUNCTION_COND_NOEXCEPT_noexcept
+#else
 #define FORBIDDEN_FUNCTION_COND_NOEXCEPT_noexcept NOT_WINDOWS(NOT_BSD(noexcept))
+#endif
 #define FORBIDDEN_FUNCTION_COND_NOEXCEPT_
 
 #ifndef FORBIDDEN_FUNCTION_IMPORT_SPEC
diff --git a/src/hotspot/share/utilities/elfFile.hpp b/src/hotspot/share/utilities/elfFile.hpp
index 0bfa821e2..76054d6fc 100644
--- a/src/hotspot/share/utilities/elfFile.hpp
+++ b/src/hotspot/share/utilities/elfFile.hpp
@@ -47,8 +47,10 @@ typedef Elf64_Phdr      Elf_Phdr;
 typedef Elf64_Sym       Elf_Sym;
 
 #if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
+#ifndef ELF_ST_TYPE
 #define ELF_ST_TYPE ELF64_ST_TYPE
 #endif
+#endif
 
 #else
 
@@ -62,7 +64,7 @@ typedef Elf32_Shdr      Elf_Shdr;
 typedef Elf32_Phdr      Elf_Phdr;
 typedef Elf32_Sym       Elf_Sym;
 
-#if !defined(_ALLBSD_SOURCE) || defined(__APPLE__)
+#if (!defined(_ALLBSD_SOURCE) || defined(__APPLE__)) && !defined(ELF_ST_TYPE)
 #define ELF_ST_TYPE ELF32_ST_TYPE
 #endif
 #endif
diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
index 302a62de6..2a07806e4 100644
--- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
+++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp
@@ -50,6 +50,10 @@
 #include <time.h>
 #include <wchar.h>
 
+#if defined(__ANDROID__) && !defined(ANDROID)
+#define ANDROID 1
+#endif
+
 #if defined(LINUX) || defined(_ALLBSD_SOURCE) || defined(_AIX)
 #include <signal.h>
 #ifndef __OpenBSD__
diff --git a/src/java.base/share/native/libtinyiconv/iconv.cpp b/src/java.base/share/native/libtinyiconv/iconv.cpp
new file mode 100644
index 000000000..7018b6ce2
--- /dev/null
+++ b/src/java.base/share/native/libtinyiconv/iconv.cpp
@@ -0,0 +1,438 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef __ANDROID__
+
+#include <ctype.h>
+#include <endian.h>
+#include <errno.h>
+#include <iconv.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <uchar.h>
+#include <wchar.h>
+
+__BEGIN_DECLS
+
+/*
+ * These return values are specified by POSIX for multibyte conversion
+ * functions.
+ */
+
+#ifdef __cplusplus
+#define __MB_ERR_ILLEGAL_SEQUENCE static_cast<size_t>(-1)
+#define __MB_ERR_INCOMPLETE_SEQUENCE static_cast<size_t>(-2)
+#else
+#define __MB_ERR_ILLEGAL_SEQUENCE (size_t)(-1)
+#define __MB_ERR_INCOMPLETE_SEQUENCE (size_t)(-2)
+#endif // __cplusplus
+#define __MB_IS_ERR(rv) (rv == __MB_ERR_ILLEGAL_SEQUENCE || \
+                         rv == __MB_ERR_INCOMPLETE_SEQUENCE)
+static inline __wur size_t mbstate_bytes_so_far(const mbstate_t* ps) {
+  return
+      (ps->__seq[2] != 0) ? 3 :
+      (ps->__seq[1] != 0) ? 2 :
+      (ps->__seq[0] != 0) ? 1 : 0;
+}
+static inline void mbstate_set_byte(mbstate_t* ps, int i, char byte) {
+  ps->__seq[i] = (uint8_t)(byte);
+}
+static inline __wur uint8_t mbstate_get_byte(const mbstate_t* ps, int n) {
+  return ps->__seq[n];
+}
+static inline __wur size_t mbstate_reset_and_return_illegal(int _errno, mbstate_t* ps) {
+  errno = _errno;
+#ifdef __cplusplus
+  *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
+#else
+  *(uint32_t*)(ps->__seq) = 0;
+#endif // __cplusplus
+  return __MB_ERR_ILLEGAL_SEQUENCE;
+}
+static inline __wur size_t mbstate_reset_and_return(int _return, mbstate_t* ps) {
+#ifdef __cplusplus
+  *(reinterpret_cast<uint32_t*>(ps->__seq)) = 0;
+#else
+  *(uint32_t*)(ps->__seq) = 0;
+#endif // __cplusplus
+  return _return;
+}
+
+#ifdef __cplusplus
+# define INVALID_ICONV_T reinterpret_cast<iconv_t>(-1)
+#else // !__cplusplus
+# define INVALID_ICONV_T (iconv_t)(-1)
+#endif // __cplusplus
+
+// Ideally we'd use icu4c but the API mismatch seems too great. So we just offer something
+// equivalent to (but slightly easier to use for runs of text than) <uchar.h>. If you're
+// here to add more encodings, consider working on finishing the icu4c NDK wrappers instead.
+
+#ifdef __cplusplus
+ enum Encoding
+#else
+ typedef enum
+#endif // __cplusplus
+{
+  US_ASCII,
+  UTF_8,
+  UTF_16_LE,
+  UTF_16_BE,
+  UTF_32_LE,
+  UTF_32_BE,
+  WCHAR_T,
+#ifdef __cplusplus
+ };
+#else
+ } Encoding;
+#endif // __cplusplus
+
+#ifdef __cplusplus
+ enum Mode
+#else
+ typedef enum
+#endif // __cplusplus
+{
+  ERROR,
+  IGNORE,
+  TRANSLIT,
+#ifdef __cplusplus
+ };
+#else
+ } Mode;
+#endif // __cplusplus
+
+// This matching is strange but true.
+// See http://www.unicode.org/reports/tr22/#Charset_Alias_Matching.
+static bool __match_encoding(const char* lhs, const char* rhs) {
+  while (*lhs && *rhs) {
+    // Skip non-alnum in lhs; "UTF-8", "UTF_8", "UTF8", "UTF 8" are all equivalent.
+    // Also implement the "delete each 0 that is not preceded by a digit" rule.
+    for (; *lhs; ++lhs) {
+      if (isalnum(*lhs) && (*lhs != '0' || !isdigit(*(lhs + 1)))) break;
+    }
+    // Case doesn't matter either.
+    if (tolower(*lhs) != tolower(*rhs)) break;
+    ++lhs;
+    ++rhs;
+  }
+  // As a special case we treat the GNU "//" extensions as end of string.
+  if ((*lhs == '\0' || strstr(lhs, "//") == lhs) && *rhs == '\0') return true;
+  return false;
+}
+
+static bool __parse_encoding(const char* s, Encoding* encoding, Mode* mode) {
+  const char* suffix = strstr(s, "//");
+  if (suffix) {
+    if (!mode) return false;
+    if (strcmp(suffix, "//IGNORE") == 0) {
+      *mode = IGNORE;
+    } else if (strcmp(suffix, "//TRANSLIT") == 0) {
+      *mode = TRANSLIT;
+    } else {
+      return false;
+    }
+  }
+  if (__match_encoding(s, "utf8")) {
+    *encoding = UTF_8;
+  } else if (__match_encoding(s, "ascii") || __match_encoding(s, "usascii")) {
+    *encoding = US_ASCII;
+  } else if (__match_encoding(s, "utf16le")) {
+    *encoding = UTF_16_LE;
+  } else if (__match_encoding(s, "utf16be")) {
+    *encoding = UTF_16_BE;
+  } else if (__match_encoding(s, "utf32le")) {
+    *encoding = UTF_32_LE;
+  } else if (__match_encoding(s, "utf32be")) {
+    *encoding = UTF_32_BE;
+  } else if (__match_encoding(s, "wchart")) {
+    *encoding = WCHAR_T;
+  } else {
+    return false;
+  }
+  return true;
+}
+
+struct __iconv_t {
+  Encoding src_encoding;
+  Encoding dst_encoding;
+  Mode mode;
+/*
+  __iconv_t() : mode(ERROR) {
+  }
+*/
+  int Convert(char** src_buf0, size_t* src_bytes_left0, char** dst_buf0, size_t* dst_bytes_left0) {
+    // Reset state.
+    wc = 0;
+    memset(&ps, 0, sizeof(ps));
+    replacement_count = 0;
+    ignored = false;
+    src_buf = src_buf0;
+    src_bytes_left = src_bytes_left0;
+    dst_buf = dst_buf0;
+    dst_bytes_left = dst_bytes_left0;
+    while (*src_bytes_left > 0) {
+      if (!GetNext() || !Convert()) return -1;
+    }
+    return Done();
+  }
+ private:
+  char32_t wc;
+  char buf[16];
+  size_t src_bytes_used;
+  size_t dst_bytes_used;
+  mbstate_t ps;
+  size_t replacement_count;
+  bool ignored;
+  char** src_buf;
+  size_t* src_bytes_left;
+  char** dst_buf;
+  size_t* dst_bytes_left;
+  bool GetNext() {
+    errno = 0;
+    switch (src_encoding) {
+      case US_ASCII:
+        wc = **src_buf;
+        src_bytes_used = 1;
+        if (wc > 0x7f) errno = EILSEQ;
+        break;
+      case UTF_8:
+        src_bytes_used = mbrtoc32(&wc, *src_buf, *src_bytes_left, &ps);
+        if (src_bytes_used == __MB_ERR_ILLEGAL_SEQUENCE) {
+          break;  // EILSEQ already set.
+        } else if (src_bytes_used == __MB_ERR_INCOMPLETE_SEQUENCE) {
+          errno = EINVAL;
+          return false;
+        }
+        break;
+      case UTF_16_BE:
+      case UTF_16_LE: {
+        if (*src_bytes_left < 2) {
+          errno = EINVAL;
+          return false;
+        }
+        bool swap = (src_encoding == UTF_16_BE);
+        wc = In16(*src_buf, swap);
+        // 0xd800-0xdbff: high surrogates
+        // 0xdc00-0xdfff: low surrogates
+        if (wc >= 0xd800 && wc <= 0xdfff) {
+          if (wc >= 0xdc00) {  // Low surrogate before high surrogate.
+            errno = EILSEQ;
+            return false;
+          }
+          if (*src_bytes_left < 4) {
+            errno = EINVAL;
+            return false;
+          }
+          uint16_t hi = wc;
+          uint16_t lo = In16(*src_buf + 2, swap);
+          wc = 0x10000 + ((hi - 0xd800) << 10) + (lo - 0xdc00);
+          src_bytes_used = 4;
+        }
+        break;
+      }
+      case UTF_32_BE:
+      case UTF_32_LE:
+      case WCHAR_T:
+        if (*src_bytes_left < 4) {
+          errno = EINVAL;
+          return false;
+        }
+        wc = In32(*src_buf, (src_encoding == UTF_32_BE));
+        break;
+    }
+    if (errno == EILSEQ) {
+      switch (mode) {
+        case ERROR:
+          return false;
+        case IGNORE:
+          *src_buf += src_bytes_used;
+          *src_bytes_left -= src_bytes_used;
+          ignored = true;
+          return GetNext();
+        case TRANSLIT:
+          wc = '?';
+          ++replacement_count;
+          return true;
+      }
+    }
+    return true;
+  }
+
+  bool Convert() {
+    errno = 0;
+    switch (dst_encoding) {
+      case US_ASCII:
+        buf[0] = wc;
+        dst_bytes_used = 1;
+        if (wc > 0x7f) errno = EILSEQ;
+        break;
+      case UTF_8:
+        dst_bytes_used = c32rtomb(buf, wc, &ps);
+        if (dst_bytes_used == __MB_ERR_ILLEGAL_SEQUENCE) {
+          break;  // EILSEQ already set.
+        } else if (dst_bytes_used == __MB_ERR_INCOMPLETE_SEQUENCE) {
+          errno = EINVAL;
+          return false;
+        }
+        break;
+      case UTF_16_BE:
+      case UTF_16_LE: {
+        bool swap = (dst_encoding == UTF_16_BE);
+        if (wc < 0x10000) {  // BMP.
+          Out16(buf, wc, swap);
+        } else {  // Supplementary plane; output surrogate pair.
+          wc -= 0x10000;
+          char16_t hi = 0xd800 | (wc >> 10);
+          char16_t lo = 0xdc00 | (wc & 0x3ff);
+          Out16(buf + 0, hi, swap);
+          Out16(buf + 2, lo, swap);
+          dst_bytes_used = 4;
+        }
+      } break;
+      case UTF_32_BE:
+      case UTF_32_LE:
+      case WCHAR_T:
+        Out32(wc, (dst_encoding == UTF_32_BE));
+        break;
+    }
+    if (errno == EILSEQ) {
+      if (mode == IGNORE) {
+        *src_buf += src_bytes_used;
+        *src_bytes_left -= src_bytes_used;
+        ignored = true;
+        return true;
+      } else if (mode == TRANSLIT) {
+        wc = '?';
+        ++replacement_count;
+        return Convert();
+      }
+      return false;
+    }
+    return Emit();
+  }
+
+  uint16_t In16(const char* buf, bool swap) {
+#ifdef __cplusplus
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
+#else // !__cplusplus
+    const uint8_t* src = (const uint8_t*)(buf);
+#endif // __cplusplus
+    uint16_t wc = (src[0]) | (src[1] << 8);
+    if (swap) wc = __swap16(wc);
+    src_bytes_used = 2;
+    return wc;
+  }
+
+  uint32_t In32(const char* buf, bool swap) {
+#ifdef __cplusplus
+    const uint8_t* src = reinterpret_cast<const uint8_t*>(buf);
+#else // !__cplusplus
+    const uint8_t* src = (const uint8_t*)(buf);
+#endif // __cplusplus
+    uint32_t wc = (src[0]) | (src[1] << 8) | (src[2] << 16) | (src[3] << 24);
+    if (swap) wc = __swap32(wc);
+    src_bytes_used = 4;
+    return wc;
+  }
+
+  void Out16(char* dst, char16_t ch, bool swap) {
+    if (swap) ch = __swap16(ch);
+    dst[0] = ch;
+    dst[1] = ch >> 8;
+    dst_bytes_used = 2;
+  }
+
+  void Out32(char32_t ch, bool swap) {
+    if (swap) ch = __swap32(ch);
+    buf[0] = ch;
+    buf[1] = ch >> 8;
+    buf[2] = ch >> 16;
+    buf[3] = ch >> 24;
+    dst_bytes_used = 4;
+  }
+
+  bool Emit() {
+    if (dst_bytes_used > *dst_bytes_left) {
+      errno = E2BIG;
+      return false;
+    }
+    memcpy(*dst_buf, buf, dst_bytes_used);
+    *src_buf += src_bytes_used;
+    *src_bytes_left -= src_bytes_used;
+    *dst_buf += dst_bytes_used;
+    *dst_bytes_left -= dst_bytes_used;
+    return true;
+  }
+
+  int Done() {
+    if (mode == TRANSLIT) return replacement_count;
+    if (ignored) {
+      errno = EILSEQ;
+      return -1;
+    }
+    return 0;
+  }
+};
+
+iconv_t iconv_open(const char* __dst_encoding, const char* __src_encoding) {
+  iconv_t result = iconv_t();
+  result->mode = ERROR;
+  if (!__parse_encoding(__src_encoding, &result->src_encoding, 0 /* nullptr */) ||
+      !__parse_encoding(__dst_encoding, &result->dst_encoding, &result->mode)) {
+    free(result);
+    errno = EINVAL;
+    return INVALID_ICONV_T;
+  }
+  return result;
+}
+
+size_t iconv(iconv_t __converter,
+             char** __src_buf, size_t* __src_bytes_left,
+             char** __dst_buf, size_t* __dst_bytes_left) {
+  if (__converter == INVALID_ICONV_T) {
+    errno = EBADF;
+    return -1;
+  }
+  return __converter->Convert(__src_buf, __src_bytes_left, __dst_buf, __dst_bytes_left);
+}
+
+int iconv_close(iconv_t __converter) {
+  if (__converter == INVALID_ICONV_T) {
+    errno = EBADF;
+    return -1;
+  }
+  free(__converter);
+  return 0;
+}
+
+__END_DECLS
+
+#endif // __ANDROID__
diff --git a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
index 2f633ad71..513c70f8b 100644
--- a/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
+++ b/src/java.base/unix/classes/sun/net/dns/ResolverConfigurationImpl.java
@@ -63,8 +63,9 @@ private ArrayList<String> resolvconf(String keyword,
         ArrayList<String> ll = new ArrayList<>();
 
         try {
+            String resolvPath = System.getProperty("ext.net.resolvPath", "/etc/resolv.conf");
             BufferedReader in =
-                new BufferedReader(new FileReader("/etc/resolv.conf"));
+                new BufferedReader(new FileReader(resolvPath));
             String line;
             while ((line = in.readLine()) != null) {
                 int maxvalues = maxperkeyword;
diff --git a/src/java.base/unix/native/libjava/ProcessImpl_md.c b/src/java.base/unix/native/libjava/ProcessImpl_md.c
index 69af948d2..1a5aaa39c 100644
--- a/src/java.base/unix/native/libjava/ProcessImpl_md.c
+++ b/src/java.base/unix/native/libjava/ProcessImpl_md.c
@@ -580,6 +580,9 @@ spawnChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath)
     c->redirectErrorStream = false;
 
     rval = posix_spawn(&resultPid, helperpath, &file_actions, 0, (char * const *) hlpargs, environ);
+#ifdef __ANDROID__
+    posix_spawn_file_actions_destroy(&file_actions);
+#endif
 
     if (rval != 0) {
         return -1;
diff --git a/src/java.base/unix/native/libjava/java_props_md.c b/src/java.base/unix/native/libjava/java_props_md.c
index 1cbc3665e..de6b4bfca 100644
--- a/src/java.base/unix/native/libjava/java_props_md.c
+++ b/src/java.base/unix/native/libjava/java_props_md.c
@@ -46,6 +46,100 @@
 #include "java_props_macosx.h"
 #endif
 
+#ifdef __ANDROID__
+// From https://android.googlesource.com/platform/bionic/+/master/libc/bionic/langinfo.cpp
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+char* nl_langinfo(nl_item item) {
+  const char* result = "";
+  switch (item) {
+    case CODESET: result = (MB_CUR_MAX == 1) ? "ASCII" : "UTF-8"; break;
+    case D_T_FMT: result = "%F %T %z"; break;
+    case D_FMT: result = "%F"; break;
+    case T_FMT: result = "%T"; break;
+    case T_FMT_AMPM: result = "%I:%M:%S %p"; break;
+    case AM_STR: result = "AM"; break;
+    case PM_STR: result = "PM"; break;
+    case DAY_1: result = "Sunday"; break;
+    case DAY_2: result = "Monday"; break;
+    case DAY_3: result = "Tuesday"; break;
+    case DAY_4: result = "Wednesday"; break;
+    case DAY_5: result = "Thursday"; break;
+    case DAY_6: result = "Friday"; break;
+    case DAY_7: result = "Saturday"; break;
+    case ABDAY_1: result = "Sun"; break;
+    case ABDAY_2: result = "Mon"; break;
+    case ABDAY_3: result = "Tue"; break;
+    case ABDAY_4: result = "Wed"; break;
+    case ABDAY_5: result = "Thu"; break;
+    case ABDAY_6: result = "Fri"; break;
+    case ABDAY_7: result = "Sat"; break;
+    case MON_1: result = "January"; break;
+    case MON_2: result = "February"; break;
+    case MON_3: result = "March"; break;
+    case MON_4: result = "April"; break;
+    case MON_5: result = "May"; break;
+    case MON_6: result = "June"; break;
+    case MON_7: result = "July"; break;
+    case MON_8: result = "August"; break;
+    case MON_9: result = "September"; break;
+    case MON_10: result = "October"; break;
+    case MON_11: result = "November"; break;
+    case MON_12: result = "December"; break;
+    case ABMON_1: result = "Jan"; break;
+    case ABMON_2: result = "Feb"; break;
+    case ABMON_3: result = "Mar"; break;
+    case ABMON_4: result = "Apr"; break;
+    case ABMON_5: result = "May"; break;
+    case ABMON_6: result = "Jun"; break;
+    case ABMON_7: result = "Jul"; break;
+    case ABMON_8: result = "Aug"; break;
+    case ABMON_9: result = "Sep"; break;
+    case ABMON_10: result = "Oct"; break;
+    case ABMON_11: result = "Nov"; break;
+    case ABMON_12: result = "Dec"; break;
+    case ERA: result = ""; break;
+    case ERA_D_FMT: result = ""; break;
+    case ERA_D_T_FMT: result = ""; break;
+    case ERA_T_FMT: result = ""; break;
+    case ALT_DIGITS: result = ""; break;
+    case RADIXCHAR: result = "."; break;
+    case THOUSEP: result = ""; break;
+    case YESEXPR: result = "^[yY]"; break;
+    case NOEXPR: result = "^[nN]"; break;
+    case CRNCYSTR: result = ""; break;
+    default: break;
+  }
+  return (char*) result;
+}
+#endif
+
 #if defined(_ALLBSD_SOURCE)
 #if !defined(P_tmpdir)
 #include <paths.h>
diff --git a/src/java.base/unix/native/libjava/jni_util_md.c b/src/java.base/unix/native/libjava/jni_util_md.c
index 7195b3def..460174f9d 100644
--- a/src/java.base/unix/native/libjava/jni_util_md.c
+++ b/src/java.base/unix/native/libjava/jni_util_md.c
@@ -31,7 +31,7 @@
 #include "jni_util.h"
 #include "dlfcn.h"
 
-#if defined(LINUX) && (defined(_GNU_SOURCE) || \
+#if !defined(__ANDROID__) && defined(LINUX) && (defined(_GNU_SOURCE) || \
          (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 200112L \
              && defined(_XOPEN_SOURCE) && _XOPEN_SOURCE < 600))
 extern int __xpg_strerror_r(int, char *, size_t);
diff --git a/src/java.base/unix/native/libjava/posix_spawn.c b/src/java.base/unix/native/libjava/posix_spawn.c
new file mode 100644
index 000000000..90936c584
--- /dev/null
+++ b/src/java.base/unix/native/libjava/posix_spawn.c
@@ -0,0 +1,197 @@
+// From https://android.googlesource.com/platform/external/dhcpcd-6.8.2/+/refs/heads/pie-dr1-release/compat/posix_spawn.c
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * All rights reserved
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* This implementation of posix_spawn is only suitable for the needs of dhcpcd
+ * but it could easily be extended to other applications. */
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "posix_spawn.h"
+
+#ifndef _NSIG
+#ifdef _SIG_MAXSIG
+#define _NSIG _SIG_MAXSIG + 1
+#else
+/* Guess */
+#define _NSIG SIGPWR + 1
+#endif
+#endif
+
+extern char **environ;
+
+static int
+posix_spawnattr_handle(const posix_spawnattr_t *attrp)
+{
+  struct sigaction sa;
+  int i;
+  if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGMASK)
+    sigprocmask(SIG_SETMASK, &attrp->posix_attr_sigmask, NULL);
+  if (attrp->posix_attr_flags & POSIX_SPAWN_SETSIGDEF) {
+    memset(&sa, 0, sizeof(sa));
+    sa.sa_handler = SIG_DFL;
+    for (i = 1; i < _NSIG; i++) {
+      if (sigismember(&attrp->posix_attr_sigdefault, i)) {
+        if (sigaction(i, &sa, NULL) == -1)
+          return -1;
+      }
+    }
+  }
+  return 0;
+}
+
+inline static int
+is_vfork_safe(short int flags)
+{
+  return !(flags & (POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK));
+}
+
+int
+posix_spawn(pid_t *pid, const char *path,
+  const posix_spawn_file_actions_t *file_actions,
+  const posix_spawnattr_t *attrp,
+  char *const argv[], char *const envp[])
+{
+  short int flags;
+  pid_t p;
+  volatile int error;
+  error = 0;
+  flags = attrp ? attrp->posix_attr_flags : 0;
+  /* dup2 file actions only touch the fd table, so they are vfork safe. */
+  if (is_vfork_safe(flags))
+    p = vfork();
+  else
+#ifdef THERE_IS_NO_FORK
+    return ENOSYS;
+#else
+    p = fork();
+#endif
+  switch (p) {
+  case -1:
+    return errno;
+  case 0:
+    if (attrp) {
+      error = posix_spawnattr_handle(attrp);
+      if (error)
+        _exit(127);
+    }
+    if (file_actions != NULL && *file_actions != NULL) {
+      const struct __posix_spawn_file_actions *fa = *file_actions;
+      int i;
+      for (i = 0; i < fa->count; i++) {
+        int from = fa->dup2_from[i], to = fa->dup2_to[i];
+        if (from == to) {
+          /* POSIX: dup2 action with identical fds clears FD_CLOEXEC */
+          int fl = fcntl(from, F_GETFD);
+          if (fl == -1 || fcntl(from, F_SETFD, fl & ~FD_CLOEXEC) == -1) {
+            error = errno;
+            _exit(127);
+          }
+        } else if (dup2(from, to) == -1) {
+          error = errno;
+          _exit(127);
+        }
+      }
+    }
+    execve(path, argv, envp);
+    error = errno;
+    _exit(127);
+  default:
+    if (error != 0)
+      waitpid(p, NULL, WNOHANG);
+    else if (pid != NULL)
+      *pid = p;
+    return error;
+  }
+}
+
+int
+posix_spawnattr_init(posix_spawnattr_t *attr)
+{
+  memset(attr, 0, sizeof(*attr));
+  attr->posix_attr_flags = 0;
+  sigprocmask(0, NULL, &attr->posix_attr_sigmask);
+  sigemptyset(&attr->posix_attr_sigdefault);
+  return 0;
+}
+
+int
+posix_spawnattr_setflags(posix_spawnattr_t *attr, short flags)
+{
+  attr->posix_attr_flags = flags;
+  return 0;
+}
+
+int
+posix_spawnattr_setsigmask(posix_spawnattr_t *attr, const sigset_t *sigmask)
+{
+  attr->posix_attr_sigmask = *sigmask;
+  return 0;
+}
+
+int
+posix_spawnattr_setsigdefault(posix_spawnattr_t *attr, const sigset_t *sigmask)
+{
+  attr->posix_attr_sigdefault = *sigmask;
+  return 0;
+}
+
+int
+posix_spawn_file_actions_init(posix_spawn_file_actions_t *fa)
+{
+  *fa = (struct __posix_spawn_file_actions *) calloc(1, sizeof(struct __posix_spawn_file_actions));
+  return *fa == NULL ? ENOMEM : 0;
+}
+
+int
+posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa)
+{
+  free(*fa);
+  *fa = NULL;
+  return 0;
+}
+
+int
+posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa, int from, int to)
+{
+  if (from < 0 || to < 0)
+    return EBADF;
+  if (*fa == NULL)
+    return EINVAL;
+  if ((*fa)->count >= COMPAT_SPAWN_MAX_ACTIONS)
+    return ENOMEM;
+  (*fa)->dup2_from[(*fa)->count] = from;
+  (*fa)->dup2_to[(*fa)->count] = to;
+  (*fa)->count++;
+  return 0;
+}
diff --git a/src/java.base/unix/native/libjava/posix_spawn.h b/src/java.base/unix/native/libjava/posix_spawn.h
new file mode 100644
index 000000000..a75c400b1
--- /dev/null
+++ b/src/java.base/unix/native/libjava/posix_spawn.h
@@ -0,0 +1,62 @@
+// From https://android.googlesource.com/platform/external/dhcpcd-6.8.2/+/refs/heads/pie-dr1-release/compat/posix_spawn.h
+/*
+ * dhcpcd - DHCP client daemon
+ * Copyright (c) 2006-2012 Roy Marples <roy@marples.name>
+ * All rights reserved
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef POSIX_SPAWN_H
+#define POSIX_SPAWN_H
+
+#include <signal.h>
+
+typedef struct {
+    short posix_attr_flags;
+#define POSIX_SPAWN_SETSIGDEF       0x10
+#define POSIX_SPAWN_SETSIGMASK      0x20
+    sigset_t posix_attr_sigmask;
+    sigset_t posix_attr_sigdefault;
+} posix_spawnattr_t;
+
+/* Binary compatible with bionic's opaque pointer type (spawn.h). Only dup2
+ * actions are supported, which is all ProcessImpl_md.c (JDK 27+) needs. */
+#define COMPAT_SPAWN_MAX_ACTIONS 32
+struct __posix_spawn_file_actions {
+  int count;
+  int dup2_from[COMPAT_SPAWN_MAX_ACTIONS];
+  int dup2_to[COMPAT_SPAWN_MAX_ACTIONS];
+};
+typedef struct __posix_spawn_file_actions* posix_spawn_file_actions_t;
+int posix_spawn_file_actions_init(posix_spawn_file_actions_t *);
+int posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *);
+int posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *, int, int);
+
+int posix_spawn(pid_t *, const char *,
+    const posix_spawn_file_actions_t *, const posix_spawnattr_t *,
+    char *const [], char *const []);
+int posix_spawnattr_init(posix_spawnattr_t *);
+int posix_spawnattr_setflags(posix_spawnattr_t *, short);
+int posix_spawnattr_setsigmask(posix_spawnattr_t *, const sigset_t *);
+int posix_spawnattr_setsigdefault(posix_spawnattr_t *, const sigset_t *);
+
+#endif
diff --git a/src/java.base/unix/native/libjli/java_md.c b/src/java.base/unix/native/libjli/java_md.c
index a75795af5..651a179ac 100644
--- a/src/java.base/unix/native/libjli/java_md.c
+++ b/src/java.base/unix/native/libjli/java_md.c
@@ -576,7 +576,58 @@ const char*
 SetExecname(char **argv)
 {
     char* exec_path = NULL;
-#if defined(__linux__)
+#if defined(__ANDROID__) //Since both __ANDROID__ and __linux__ are defined, we must let the preprocessor preprocess the __ANDRIOD__ part first
+    char *__java_home = getenv("JAVA_HOME");
+    // From http://hg.openjdk.java.net/mobile/jdk9/jdk/file/17bb8a98d5e3/src/java.base/unix/native/libjli/java_md_solinux.c#l844
+        /* For Android, 'self' would point to /system/bin/app_process
+         * since we are really executing a Dalvik program at this point.
+         * argv[0] points to the Dalvik application name and we set the
+         * path to __java_home.
+         */
+        char buf[PATH_MAX+1];
+        char *p = NULL;
+        if ((p = JLI_StrRChr(argv[0], '/')) != 0) {
+          /* may be running from command line */
+          p++;
+          if ((JLI_StrLen(p) == 4) && JLI_StrCmp(p, "java") == 0) {
+            /* started as 'java'. Must be command line */
+            JLI_TraceLauncher("SetExecName maybe command line = %s\n", argv[0]);
+            if (*argv[0] != '/') {
+              char *curdir = NULL;
+              /* get absolute path */
+              getcwd(buf, PATH_MAX);
+              curdir = JLI_StringDup(buf);
+              JLI_Snprintf(buf, PATH_MAX, "%s/%s", curdir, argv[0]);
+              JLI_MemFree(curdir);
+            } else {
+              JLI_Snprintf(buf, PATH_MAX, "%s", argv[0]);
+            }
+          } else {
+            /* Not command line, see if __java_home set */
+            if (__java_home != NULL) {
+              JLI_TraceLauncher("SetExecName not java = %s\n", __java_home);
+              JLI_Snprintf(buf, PATH_MAX, "%s/bin/java", __java_home);
+            } else {
+              /* Fake it as best we can or should we punt? */
+              JLI_TraceLauncher("SetExecName fake it = %s\n", argv[0]);
+              JLI_Snprintf(buf, PATH_MAX, "/data/data/%s/storage/jvm/bin/java",
+                           argv[0]);
+            }
+          }
+        } else {
+            /* Not started as 'java', see if __java_home set */
+            if (__java_home != NULL) {
+              JLI_TraceLauncher("SetExecName not command line = %s\n", __java_home);
+              JLI_Snprintf(buf, PATH_MAX, "%s/bin/java", __java_home);
+            } else {
+              /* Fake it as best we can or should we punt? */
+              JLI_TraceLauncher("SetExecName fake it 2 = %s\n", argv[0]);
+              JLI_Snprintf(buf, PATH_MAX, "/data/data/%s/storage/jvm/bin/java",
+                           argv[0]);
+            }
+        }
+        exec_path = JLI_StringDup(buf);
+#elif defined(__linux__)
     {
         const char* self = "/proc/self/exe";
         char buf[PATH_MAX+1];
@@ -586,10 +637,6 @@ SetExecname(char **argv)
             exec_path = JLI_StringDup(buf);
         }
     }
-#else /* !__linux__ */
-    {
-        /* Not implemented */
-    }
 #endif
 
     if (exec_path == NULL) {
diff --git a/src/java.base/unix/native/libnet/net_util_md.h b/src/java.base/unix/native/libnet/net_util_md.h
index 639cf0051..b9fa162ff 100644
--- a/src/java.base/unix/native/libnet/net_util_md.h
+++ b/src/java.base/unix/native/libnet/net_util_md.h
@@ -26,6 +26,9 @@
 #ifndef NET_UTILS_MD_H
 #define NET_UTILS_MD_H
 
+#ifdef ANDROID
+#include <netinet/in.h>
+#endif
 #include <netdb.h>
 #include <poll.h>
 #include <sys/socket.h>
diff --git a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
index 4b5cfabeb..ad2577495 100644
--- a/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
+++ b/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c
@@ -217,6 +217,41 @@ static fdopendir_func* my_fdopendir_func = NULL;
 static statx_func* my_statx_func = NULL;
 #endif
 
+#ifdef __ANDROID__
+/*
+ * TODO: Android lacks support for the methods listed below.  In it's place are
+ * alternatives that use existing Android functionality, but lack reentrant
+ * support.  Determine if the following are the most suitable alternatives.
+ *
+ */
+int getgrgid_r(gid_t gid, struct group* grp, char* buf, size_t buflen, struct group** result) {
+
+  *result = NULL;
+  errno = 0;
+  grp = getgrgid(gid);
+  if (grp == NULL) {
+        return errno;
+  }
+  // buf not used by caller (see below)
+  *result = grp;
+  return 0;
+}
+
+int getgrnam_r(const char *name, struct group* grp, char* buf, size_t buflen, struct group** result) {
+
+  *result = NULL;
+  errno = 0;
+  grp = getgrnam(name);
+  if (grp == NULL) {
+        return errno;
+  }
+  // buf not used by caller (see below)
+  *result = grp;
+  return 0;
+
+}
+#endif
+
 /**
  * fstatat missing from glibc on Linux.
  */
@@ -375,7 +410,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this)
 #ifdef _DARWIN_FEATURE_64_BIT_INODE
     capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME;
 #endif
-#if defined(__linux__)
+#if defined(__linux__) && !defined(__ANDROID__)
     my_statx_func = (statx_func*) dlsym(RTLD_DEFAULT, "statx");
     if (my_statx_func != NULL) {
         capabilities |= sun_nio_fs_UnixNativeDispatcher_SUPPORTS_BIRTHTIME;
diff --git a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c
index af50fdbb5..a061154da 100644
--- a/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c
+++ b/src/java.desktop/unix/native/libawt/awt/awt_LoadLibrary.c
@@ -30,6 +30,7 @@
 #include <jni.h>
 #include <jni_util.h>
 #include <jvm.h>
+#include <stdbool.h>
 #include "gdefs.h"
 
 #include <sys/param.h>
@@ -95,6 +96,30 @@ JNIEXPORT jboolean JNICALL AWTIsHeadless() {
   #define HEADLESS_PATH "/libawt_headless.so"
 #endif
 
+static bool read_so_path_from_maps(const char* so_name, char* buf) {
+  FILE *fp = fopen("/proc/self/maps", "r");
+
+  if (!fp) {
+    return false;
+  }
+
+  char maps_buffer[2048];
+  while (fgets(maps_buffer, 2048, fp) != NULL) {
+    if (strstr(maps_buffer, so_name) == NULL) {
+      continue;
+    }
+
+    char *so_path = strchr(maps_buffer, '/');
+    so_path[strlen(so_path) - 1] = '\0'; // Cut trailing \n
+      strcpy(buf,so_path);
+    fclose(fp);
+    return true;
+  }
+
+  fclose(fp);
+  return false;
+}
+
 jint
 AWT_OnLoad(JavaVM *vm, void *reserved)
 {
@@ -136,6 +161,8 @@ AWT_OnLoad(JavaVM *vm, void *reserved)
         dladdr((void *)AWT_OnLoad, &dlinfo);
         if (realpath((char *)dlinfo.dli_fname, buf) == NULL) {
             perror((char *)dlinfo.dli_fname);
+        } else{
+            read_so_path_from_maps(dlinfo.dli_fname, buf);
         }
         len = strlen(buf);
         p = strrchr(buf, '/');
diff --git a/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c b/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c
index 490eea9a5..27ee1c23e 100644
--- a/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c
+++ b/src/java.instrument/unix/native/libinstrument/EncodingSupport_md.c
@@ -65,7 +65,11 @@ utfInitialize(void)
     (void)setlocale(LC_ALL, "");
 
     /* Get the codeset name */
+#ifndef __ANDROID__
     codeset = (char*)nl_langinfo(CODESET);
+#else
+    codeset = "ASCII"; // (MB_CUR_MAX == 1) ? "ASCII" : "UTF-8";
+#endif
     if ( codeset == NULL || codeset[0] == 0 ) {
         UTF_DEBUG(("NO codeset returned by nl_langinfo(CODESET)\n"));
         return;
diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c b/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c
index 6bae02fce..9cf2a7ab4 100644
--- a/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c
+++ b/src/jdk.jdwp.agent/share/native/libjdwp/utf_util.c
@@ -483,7 +483,11 @@ static int iconvConvert(conv_direction drn, char *bytes, size_t len, char *outpu
         // locale is not initialized, do it now
         if (setlocale(LC_ALL, "") != NULL) {
             // nl_langinfo returns ANSI_X3.4-1968 by default
+#ifndef __ANDROID__
             codeset = (char*)nl_langinfo(CODESET);
+#else
+            codeset = "ASCII";
+#endif
         }
 
         if (codeset == NULL) {
