Merge JDK-8200758-branch
authorherrick
Fri, 28 Jun 2019 16:49:32 -0400
branchJDK-8200758-branch
changeset 57443 c71ef0329ac6
parent 57439 dd706e28e6cc (current diff)
parent 55525 c9093341cfe2 (diff)
child 57444 91e9d4691e5e
Merge
--- a/src/hotspot/cpu/aarch64/aarch64.ad	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/aarch64.ad	Fri Jun 28 16:49:32 2019 -0400
@@ -1761,6 +1761,17 @@
   // branch if we need to invalidate the method later
   __ nop();
 
+  if (C->clinit_barrier_on_entry()) {
+    assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started");
+
+    Label L_skip_barrier;
+
+    __ mov_metadata(rscratch2, C->method()->holder()->constant_encoding());
+    __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
+    __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+    __ bind(L_skip_barrier);
+  }
+  
   int bangsize = C->bang_size_in_bytes();
   if (C->need_stack_bang(bangsize) && UseStackBanging)
     __ generate_stack_overflow_check(bangsize);
--- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -317,7 +317,15 @@
 }
 
 void LIR_Assembler::clinit_barrier(ciMethod* method) {
-  ShouldNotReachHere(); // not implemented
+  assert(VM_Version::supports_fast_class_init_checks(), "sanity");
+  assert(!method->holder()->is_not_initialized(), "initialization should have been started");
+
+  Label L_skip_barrier;
+
+  __ mov_metadata(rscratch2, method->holder()->constant_encoding());
+  __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier /*L_fast_path*/);
+  __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+  __ bind(L_skip_barrier);
 }
 
 void LIR_Assembler::jobject2reg(jobject o, Register reg) {
--- a/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/c1_MacroAssembler_aarch64.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -331,11 +331,6 @@
 
 
 void C1_MacroAssembler::build_frame(int framesize, int bang_size_in_bytes) {
-  // If we have to make this method not-entrant we'll overwrite its
-  // first instruction with a jump.  For this action to be legal we
-  // must ensure that this first instruction is a B, BL, NOP, BKPT,
-  // SVC, HVC, or SMC.  Make it a NOP.
-  nop();
   assert(bang_size_in_bytes >= framesize, "stack bang size incorrect");
   // Make sure there is enough stack space for this method's activation.
   // Note that we do this before doing an enter().
@@ -355,6 +350,11 @@
 
 
 void C1_MacroAssembler::verified_entry() {
+  // If we have to make this method not-entrant we'll overwrite its
+  // first instruction with a jump.  For this action to be legal we
+  // must ensure that this first instruction is a B, BL, NOP, BKPT,
+  // SVC, HVC, or SMC.  Make it a NOP.
+  nop();
 }
 
 void C1_MacroAssembler::load_parameter(int offset_in_words, Register reg) {
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -288,6 +288,18 @@
   ldr(klass, Address(klass, Array<Klass*>::base_offset_in_bytes()));
 }
 
+void InterpreterMacroAssembler::load_resolved_method_at_index(int byte_no,
+                                                              Register method,
+                                                              Register cache) {
+  const int method_offset = in_bytes(
+    ConstantPoolCache::base_offset() +
+      ((byte_no == TemplateTable::f2_byte)
+       ? ConstantPoolCacheEntry::f2_offset()
+       : ConstantPoolCacheEntry::f1_offset()));
+
+  ldr(method, Address(cache, method_offset)); // get f1 Method*
+}
+
 // Generate a subtype check: branch to ok_is_subtype if sub_klass is a
 // subtype of super_klass.
 //
--- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -124,6 +124,8 @@
   // load cpool->resolved_klass_at(index);
   void load_resolved_klass_at_offset(Register cpool, Register index, Register klass, Register temp);
 
+  void load_resolved_method_at_index(int byte_no, Register method, Register cache);
+
   void pop_ptr(Register r = r0);
   void pop_i(Register r = r0);
   void pop_l(Register r = r0);
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -1307,6 +1307,35 @@
   bind(L_fallthrough);
 }
 
+void MacroAssembler::clinit_barrier(Register klass, Register scratch, Label* L_fast_path, Label* L_slow_path) {
+  assert(L_fast_path != NULL || L_slow_path != NULL, "at least one is required");
+  assert_different_registers(klass, rthread, scratch);
+
+  Label L_fallthrough, L_tmp;
+  if (L_fast_path == NULL) {
+    L_fast_path = &L_fallthrough;
+  } else if (L_slow_path == NULL) {
+    L_slow_path = &L_fallthrough;
+  }
+  // Fast path check: class is fully initialized
+  ldrb(scratch, Address(klass, InstanceKlass::init_state_offset()));
+  subs(zr, scratch, InstanceKlass::fully_initialized);
+  br(Assembler::EQ, *L_fast_path);
+
+  // Fast path check: current thread is initializer thread
+  ldr(scratch, Address(klass, InstanceKlass::init_thread_offset()));
+  cmp(rthread, scratch);
+
+  if (L_slow_path == &L_fallthrough) {
+    br(Assembler::EQ, *L_fast_path);
+    bind(*L_slow_path);
+  } else if (L_fast_path == &L_fallthrough) {
+    br(Assembler::NE, *L_slow_path);
+    bind(*L_fast_path);
+  } else {
+    Unimplemented();
+  }
+}
 
 void MacroAssembler::verify_oop(Register reg, const char* s) {
   if (!VerifyOops) return;
@@ -3683,6 +3712,12 @@
   bs->obj_equals(this, obj1, obj2);
 }
 
+void MacroAssembler::load_method_holder(Register holder, Register method) {
+  ldr(holder, Address(method, Method::const_offset()));                      // ConstMethod*
+  ldr(holder, Address(holder, ConstMethod::constants_offset()));             // ConstantPool*
+  ldr(holder, Address(holder, ConstantPool::pool_holder_offset_in_bytes())); // InstanceKlass*
+}
+
 void MacroAssembler::load_klass(Register dst, Register src) {
   if (UseCompressedClassPointers) {
     ldrw(dst, Address(src, oopDesc::klass_offset_in_bytes()));
--- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -788,6 +788,8 @@
   // C 'boolean' to Java boolean: x == 0 ? 0 : 1
   void c2bool(Register x);
 
+  void load_method_holder(Register holder, Register method);
+
   // oop manipulations
   void load_klass(Register dst, Register src);
   void store_klass(Register dst, Register src);
@@ -926,6 +928,11 @@
                            Register temp_reg,
                            Label& L_success);
 
+  void clinit_barrier(Register klass,
+                      Register thread,
+                      Label* L_fast_path = NULL,
+                      Label* L_slow_path = NULL);
+
   Address argument_address(RegisterOrConstant arg_slot, int extra_slot_offset = 0);
 
 
--- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -799,6 +799,22 @@
   }
 #endif
 
+  // Class initialization barrier for static methods
+  if (VM_Version::supports_fast_class_init_checks()) {
+    Label L_skip_barrier;
+
+    { // Bypass the barrier for non-static methods
+      __ ldrw(rscratch1, Address(rmethod, Method::access_flags_offset()));
+      __ andsw(zr, rscratch1, JVM_ACC_STATIC);
+      __ br(Assembler::EQ, L_skip_barrier); // non-static
+    }
+
+    __ load_method_holder(rscratch2, rmethod);
+    __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
+    __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+    __ bind(L_skip_barrier);
+  }
+
   gen_c2i_adapter(masm, total_args_passed, comp_args_on_stack, sig_bt, regs, skip_fixup);
 
   __ flush();
@@ -1580,6 +1596,15 @@
   // SVC, HVC, or SMC.  Make it a NOP.
   __ nop();
 
+  if (VM_Version::supports_fast_class_init_checks() && method->needs_clinit_barrier()) {
+    Label L_skip_barrier;
+    __ mov_metadata(rscratch2, method->method_holder()); // InstanceKlass*
+    __ clinit_barrier(rscratch2, rscratch1, &L_skip_barrier);
+    __ far_jump(RuntimeAddress(SharedRuntime::get_handle_wrong_method_stub()));
+
+    __ bind(L_skip_barrier);
+  }
+
   // Generate stack overflow check
   if (UseStackBanging) {
     __ bang_stack_with_offset(JavaThread::stack_shadow_zone_size());
--- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -2323,7 +2323,7 @@
   const Register temp = r19;
   assert_different_registers(Rcache, index, temp);
 
-  Label resolved;
+  Label resolved, clinit_barrier_slow;
 
   Bytecodes::Code code = bytecode();
   switch (code) {
@@ -2338,6 +2338,8 @@
   __ br(Assembler::EQ, resolved);
 
   // resolve first time through
+  // Class initialization barrier slow path lands here as well.
+  __ bind(clinit_barrier_slow);
   address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
   __ mov(temp, (int) code);
   __ call_VM(noreg, entry, temp);
@@ -2347,6 +2349,13 @@
   // n.b. unlike x86 Rcache is now rcpool plus the indexed offset
   // so all clients ofthis method must be modified accordingly
   __ bind(resolved);
+
+  // Class initialization barrier for static methods
+  if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
+    __ load_resolved_method_at_index(byte_no, temp, Rcache);
+    __ load_method_holder(temp, temp);
+    __ clinit_barrier(temp, rscratch1, NULL, &clinit_barrier_slow);
+  }
 }
 
 // The Rcache and index registers must be set before call
@@ -3418,9 +3427,8 @@
   __ profile_virtual_call(r3, r13, r19);
 
   // Get declaring interface class from method, and itable index
-  __ ldr(r0, Address(rmethod, Method::const_offset()));
-  __ ldr(r0, Address(r0, ConstMethod::constants_offset()));
-  __ ldr(r0, Address(r0, ConstantPool::pool_holder_offset_in_bytes()));
+
+  __ load_method_holder(r0, rmethod);
   __ ldrw(rmethod, Address(rmethod, Method::itable_index_offset()));
   __ subw(rmethod, rmethod, Method::itable_index_max);
   __ negw(rmethod, rmethod);
--- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -124,6 +124,7 @@
   static int dcache_line_size() {
     return (1 << ((_psr_info.ctr_el0 >> 16) & 0x0f)) * 4;
   }
+  static bool supports_fast_class_init_checks() { return true; }
 };
 
 #endif // CPU_AARCH64_VM_VERSION_AARCH64_HPP
--- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.
  * Copyright 2007, 2008, 2010, 2015 Red Hat, Inc.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -156,9 +156,11 @@
     StubRoutines::_oop_arraycopy             = ShouldNotCallThisStub();
 
     StubRoutines::_checkcast_arraycopy       = ShouldNotCallThisStub();
-    StubRoutines::_unsafe_arraycopy          = ShouldNotCallThisStub();
     StubRoutines::_generic_arraycopy         = ShouldNotCallThisStub();
 
+    // Shared code tests for "NULL" to discover the stub is not generated.
+    StubRoutines::_unsafe_arraycopy          = NULL;
+
     // We don't generate specialized code for HeapWord-aligned source
     // arrays, so just use the code we've already generated
     StubRoutines::_arrayof_jbyte_disjoint_arraycopy =
--- a/src/hotspot/os/aix/os_aix.inline.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/aix/os_aix.inline.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -37,11 +37,6 @@
 #include <sys/ioctl.h>
 #include <netdb.h>
 
-// File names are case-insensitive on windows only.
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/bsd/os_bsd.inline.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/bsd/os_bsd.inline.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -35,11 +35,6 @@
 #include <poll.h>
 #include <netdb.h>
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/linux/os_linux.inline.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/linux/os_linux.inline.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -35,11 +35,6 @@
 #include <poll.h>
 #include <netdb.h>
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/posix/os_posix.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/posix/os_posix.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -1450,6 +1450,30 @@
   return path;
 }
 
+bool os::same_files(const char* file1, const char* file2) {
+  if (strcmp(file1, file2) == 0) {
+    return true;
+  }
+
+  bool is_same = false;
+  struct stat st1;
+  struct stat st2;
+
+  if (os::stat(file1, &st1) < 0) {
+    return false;
+  }
+
+  if (os::stat(file2, &st2) < 0) {
+    return false;
+  }
+
+  if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
+    // same files
+    is_same = true;
+  }
+  return is_same;
+}
+
 // Check minimum allowable stack sizes for thread creation and to initialize
 // the java system classes, including StackOverflowError - depends on page
 // size.
--- a/src/hotspot/os/solaris/os_solaris.inline.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/solaris/os_solaris.inline.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -37,11 +37,6 @@
 #include <netdb.h>
 #include <setjmp.h>
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s1, const char* s2, size_t num) {
-  return strncmp(s1, s2, num);
-}
-
 inline bool os::uses_stack_guard_pages() {
   return true;
 }
--- a/src/hotspot/os/windows/os_windows.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -4367,6 +4367,88 @@
   return ret;
 }
 
+static HANDLE create_read_only_file_handle(const char* file) {
+  if (file == NULL) {
+    return INVALID_HANDLE_VALUE;
+  }
+
+  char* nativepath = (char*)os::strdup(file, mtInternal);
+  if (nativepath == NULL) {
+    errno = ENOMEM;
+    return INVALID_HANDLE_VALUE;
+  }
+  os::native_path(nativepath);
+
+  size_t len = strlen(nativepath);
+  HANDLE handle = INVALID_HANDLE_VALUE;
+
+  if (len < MAX_PATH) {
+    handle = ::CreateFile(nativepath, 0, FILE_SHARE_READ,
+                          NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+  } else {
+    errno_t err = ERROR_SUCCESS;
+    wchar_t* wfile = create_unc_path(nativepath, err);
+    if (err != ERROR_SUCCESS) {
+      if (wfile != NULL) {
+        destroy_unc_path(wfile);
+      }
+      os::free(nativepath);
+      return INVALID_HANDLE_VALUE;
+    }
+    handle = ::CreateFileW(wfile, 0, FILE_SHARE_READ,
+                           NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    destroy_unc_path(wfile);
+  }
+
+  os::free(nativepath);
+  return handle;
+}
+
+bool os::same_files(const char* file1, const char* file2) {
+
+  if (file1 == NULL && file2 == NULL) {
+    return true;
+  }
+
+  if (file1 == NULL || file2 == NULL) {
+    return false;
+  }
+
+  if (strcmp(file1, file2) == 0) {
+    return true;
+  }
+
+  HANDLE handle1 = create_read_only_file_handle(file1);
+  HANDLE handle2 = create_read_only_file_handle(file2);
+  bool result = false;
+
+  // if we could open both paths...
+  if (handle1 != INVALID_HANDLE_VALUE && handle2 != INVALID_HANDLE_VALUE) {
+    BY_HANDLE_FILE_INFORMATION fileInfo1;
+    BY_HANDLE_FILE_INFORMATION fileInfo2;
+    if (::GetFileInformationByHandle(handle1, &fileInfo1) &&
+      ::GetFileInformationByHandle(handle2, &fileInfo2)) {
+      // the paths are the same if they refer to the same file (fileindex) on the same volume (volume serial number)
+      if (fileInfo1.dwVolumeSerialNumber == fileInfo2.dwVolumeSerialNumber &&
+        fileInfo1.nFileIndexHigh == fileInfo2.nFileIndexHigh &&
+        fileInfo1.nFileIndexLow == fileInfo2.nFileIndexLow) {
+        result = true;
+      }
+    }
+  }
+
+  //free the handles
+  if (handle1 != INVALID_HANDLE_VALUE) {
+    ::CloseHandle(handle1);
+  }
+
+  if (handle2 != INVALID_HANDLE_VALUE) {
+    ::CloseHandle(handle2);
+  }
+
+  return result;
+}
+
 
 #define FT2INT64(ft) \
   ((jlong)((jlong)(ft).dwHighDateTime << 32 | (julong)(ft).dwLowDateTime))
--- a/src/hotspot/os/windows/os_windows.inline.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/os/windows/os_windows.inline.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -32,11 +32,6 @@
 
 inline const int os::default_file_open_flags() { return O_BINARY | O_NOINHERIT;}
 
-// File names are case-insensitive on windows only
-inline int os::file_name_strncmp(const char* s, const char* t, size_t num) {
-  return _strnicmp(s, t, num);
-}
-
 inline void  os::dll_unload(void *lib) {
   ::FreeLibrary((HMODULE)lib);
 }
--- a/src/hotspot/share/classfile/classLoader.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/classfile/classLoader.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -292,11 +292,13 @@
   return NULL;
 }
 
-ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append) : ClassPathEntry() {
+ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name,
+                                     bool is_boot_append, bool from_class_path_attr) : ClassPathEntry() {
   _zip = zip;
   char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
   strcpy(copy, zip_name);
   _zip_name = copy;
+  _from_class_path_attr = from_class_path_attr;
 }
 
 ClassPathZipEntry::~ClassPathZipEntry() {
@@ -577,7 +579,7 @@
     strncpy(path, &class_path[start], end - start);
     path[end - start] = '\0';
 
-    update_class_path_entry_list(path, false, false);
+    update_class_path_entry_list(path, false, false, false);
 
     while (class_path[end] == os::path_separator()[0]) {
       end++;
@@ -612,7 +614,7 @@
   // File or directory found
   ClassPathEntry* new_entry = NULL;
   new_entry = create_class_path_entry(path, &st, true /* throw_exception */,
-                                      false /*is_boot_append */, CHECK);
+                                      false /*is_boot_append */, false /* from_class_path_attr */, CHECK);
   if (new_entry == NULL) {
     return;
   }
@@ -668,7 +670,7 @@
       struct stat st;
       if (os::stat(path, &st) == 0) {
         // File or directory found
-        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, false, CHECK);
         // If the path specification is valid, enter it into this module's list
         if (new_entry != NULL) {
           module_cpl->add_to_list(new_entry);
@@ -737,7 +739,7 @@
       struct stat st;
       if (os::stat(path, &st) == 0) {
         // Directory found
-        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+        ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, false, CHECK);
 
         // Check for a jimage
         if (Arguments::has_jimage()) {
@@ -754,7 +756,7 @@
     } else {
       // Every entry on the system boot class path after the initial base piece,
       // which is set by os::set_boot_path(), is considered an appended entry.
-      update_class_path_entry_list(path, false, true);
+      update_class_path_entry_list(path, false, true, false);
     }
 
     while (class_path[end] == os::path_separator()[0]) {
@@ -782,7 +784,7 @@
   struct stat st;
   if (os::stat(path, &st) == 0) {
     // Directory found
-    ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, CHECK);
+    ClassPathEntry* new_entry = create_class_path_entry(path, &st, false, false, false, CHECK);
 
     // If the path specification is valid, enter it into this module's list.
     // There is no need to check for duplicate modules in the exploded entry list,
@@ -802,7 +804,9 @@
 
 ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
                                                      bool throw_exception,
-                                                     bool is_boot_append, TRAPS) {
+                                                     bool is_boot_append,
+                                                     bool from_class_path_attr,
+                                                     TRAPS) {
   JavaThread* thread = JavaThread::current();
   ClassPathEntry* new_entry = NULL;
   if ((st->st_mode & S_IFMT) == S_IFREG) {
@@ -832,7 +836,7 @@
         zip = (*ZipOpen)(canonical_path, &error_msg);
       }
       if (zip != NULL && error_msg == NULL) {
-        new_entry = new ClassPathZipEntry(zip, path, is_boot_append);
+        new_entry = new ClassPathZipEntry(zip, path, is_boot_append, from_class_path_attr);
       } else {
         char *msg;
         if (error_msg == NULL) {
@@ -882,7 +886,7 @@
         }
         if (zip != NULL && error_msg == NULL) {
           // create using canonical path
-          return new ClassPathZipEntry(zip, canonical_path, is_boot_append);
+          return new ClassPathZipEntry(zip, canonical_path, is_boot_append, false);
         }
       }
     }
@@ -956,13 +960,14 @@
 bool ClassLoader::update_class_path_entry_list(const char *path,
                                                bool check_for_duplicates,
                                                bool is_boot_append,
+                                               bool from_class_path_attr,
                                                bool throw_exception) {
   struct stat st;
   if (os::stat(path, &st) == 0) {
     // File or directory found
     ClassPathEntry* new_entry = NULL;
     Thread* THREAD = Thread::current();
-    new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, CHECK_(false));
+    new_entry = create_class_path_entry(path, &st, throw_exception, is_boot_append, from_class_path_attr, CHECK_(false));
     if (new_entry == NULL) {
       return false;
     }
--- a/src/hotspot/share/classfile/classLoader.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/classfile/classLoader.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -53,6 +53,8 @@
   void set_next(ClassPathEntry* next);
   virtual bool is_modules_image() const = 0;
   virtual bool is_jar_file() const = 0;
+  // Is this entry created from the "Class-path" attribute from a JAR Manifest?
+  virtual bool from_class_path_attr() const = 0;
   virtual const char* name() const = 0;
   virtual JImageFile* jimage() const = 0;
   virtual void close_jimage() = 0;
@@ -73,6 +75,7 @@
  public:
   bool is_modules_image() const { return false; }
   bool is_jar_file() const { return false;  }
+  bool from_class_path_attr() const { return false; }
   const char* name() const { return _dir; }
   JImageFile* jimage() const { return NULL; }
   void close_jimage() {}
@@ -99,13 +102,15 @@
  private:
   jzfile* _zip;              // The zip archive
   const char*   _zip_name;   // Name of zip archive
+  bool _from_class_path_attr; // From the "Class-path" attribute of a jar file
  public:
   bool is_modules_image() const { return false; }
   bool is_jar_file() const { return true;  }
+  bool from_class_path_attr() const { return _from_class_path_attr; }
   const char* name() const { return _zip_name; }
   JImageFile* jimage() const { return NULL; }
   void close_jimage() {}
-  ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append);
+  ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append, bool from_class_path_attr);
   virtual ~ClassPathZipEntry();
   u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
   ClassFileStream* open_stream(const char* name, TRAPS);
@@ -122,6 +127,7 @@
 public:
   bool is_modules_image() const;
   bool is_jar_file() const { return false; }
+  bool from_class_path_attr() const { return false; }
   bool is_open() const { return _jimage != NULL; }
   const char* name() const { return _name == NULL ? "" : _name; }
   JImageFile* jimage() const { return _jimage; }
@@ -257,7 +263,8 @@
  public:
   static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
                                                  bool throw_exception,
-                                                 bool is_boot_append, TRAPS);
+                                                 bool is_boot_append,
+                                                 bool from_class_path_attr, TRAPS);
 
   // If the package for the fully qualified class name is in the boot
   // loader's package entry table then add_package() sets the classpath_index
@@ -281,6 +288,7 @@
   static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
                                            bool is_boot_append,
+                                           bool from_class_path_attr,
                                            bool throw_exception=true);
   CDS_ONLY(static void update_module_path_entry_list(const char *path, TRAPS);)
   static void print_bootclasspath();
--- a/src/hotspot/share/classfile/classLoaderExt.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/classfile/classLoaderExt.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -213,7 +213,7 @@
         int n = os::snprintf(libname, libname_len + 1, "%.*s%s", dir_len, dir_name, file_start);
         assert((size_t)n == libname_len, "Unexpected number of characters in string");
         trace_class_path("library = ", libname);
-        ClassLoader::update_class_path_entry_list(libname, true, false);
+        ClassLoader::update_class_path_entry_list(libname, true, false, true /* from_class_path_attr */);
       }
 
       file_start = file_end;
@@ -339,7 +339,7 @@
   }
   ClassPathEntry* new_entry = NULL;
 
-  new_entry = create_class_path_entry(path, &st, false, false, CHECK_NULL);
+  new_entry = create_class_path_entry(path, &st, false, false, false, CHECK_NULL);
   if (new_entry == NULL) {
     return NULL;
   }
--- a/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/classfile/sharedPathsMiscInfo.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -153,83 +153,10 @@
   return true;
 }
 
-char* skip_first_path_entry(const char* path) {
-  size_t path_sep_len = strlen(os::path_separator());
-  char* p = strstr((char*)path, os::path_separator());
-  if (p != NULL) {
-    debug_only( {
-      size_t image_name_len = strlen(MODULES_IMAGE_NAME);
-      assert(strncmp(p - image_name_len, MODULES_IMAGE_NAME, image_name_len) == 0,
-             "first entry must be the modules image");
-    } );
-    p += path_sep_len;
-  } else {
-    debug_only( {
-      assert(ClassLoader::string_ends_with(path, MODULES_IMAGE_NAME),
-             "first entry must be the modules image");
-    } );
-  }
-  return p;
-}
-
 bool SharedPathsMiscInfo::check(jint type, const char* path, bool is_static) {
   assert(UseSharedSpaces, "runtime only");
   switch (type) {
   case BOOT_PATH:
-    {
-      //
-      // - Archive contains boot classes only - relaxed boot path check:
-      //   Extra path elements appended to the boot path at runtime are allowed.
-      //
-      // - Archive contains application or platform classes - strict boot path check:
-      //   Validate the entire runtime boot path, which must be compactible
-      //   with the dump time boot path. Appending boot path at runtime is not
-      //   allowed.
-      //
-
-      // The first entry in boot path is the modules_image (guaranteed by
-      // ClassLoader::setup_boot_search_path()). Skip the first entry. The
-      // path of the runtime modules_image may be different from the dump
-      // time path (e.g. the JDK image is copied to a different location
-      // after generating the shared archive), which is acceptable. For most
-      // common cases, the dump time boot path might contain modules_image only.
-      char* runtime_boot_path = Arguments::get_sysclasspath();
-      char* rp = skip_first_path_entry(runtime_boot_path);
-      char* dp = skip_first_path_entry(path);
-
-      bool relaxed_check = is_static ?
-                             !FileMapInfo::current_info()->header()->has_platform_or_app_classes() :
-                             !FileMapInfo::dynamic_info()->header()->has_platform_or_app_classes();
-      if (dp == NULL && rp == NULL) {
-        break;   // ok, both runtime and dump time boot paths have modules_images only
-      } else if (dp == NULL && rp != NULL && relaxed_check) {
-        break;   // ok, relaxed check, runtime has extra boot append path entries
-      } else if (dp != NULL && rp != NULL) {
-        size_t num;
-        size_t dp_len = strlen(dp);
-        size_t rp_len = strlen(rp);
-        if (rp_len >= dp_len) {
-          if (relaxed_check) {
-            // only check the leading entries in the runtime boot path, up to
-            // the length of the dump time boot path
-            num = dp_len;
-          } else {
-            // check the full runtime boot path, must match with dump time
-            num = rp_len;
-          }
-
-          if (os::file_name_strncmp(dp, rp, num) == 0) {
-            // make sure it is the end of an entry in the runtime boot path
-            if (rp[dp_len] == '\0' || rp[dp_len] == os::path_separator()[0]) {
-              break; // ok, runtime and dump time paths match
-            }
-          }
-        }
-      }
-
-      // The paths are different
-      return fail("[BOOT classpath mismatch, actual =", runtime_boot_path);
-    }
     break;
   case NON_EXIST:
     {
@@ -242,22 +169,6 @@
     }
     break;
   case APP_PATH:
-    {
-      size_t len = strlen(path);
-      const char *appcp = Arguments::get_appclasspath();
-      assert(appcp != NULL, "NULL app classpath");
-      size_t appcp_len = strlen(appcp);
-      if (appcp_len < len) {
-        return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
-      }
-      // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
-      if (os::file_name_strncmp(path, appcp, len) != 0) {
-        return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
-      }
-      if (appcp[len] != '\0' && appcp[len] != os::path_separator()[0]) {
-        return fail("Dump time APP classpath is not a proper prefix of run time APP classpath: ", appcp);
-      }
-    }
     break;
   default:
     return fail("Corrupted archive file header");
--- a/src/hotspot/share/memory/filemap.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/memory/filemap.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -75,7 +75,7 @@
 // an archive file should stop the process.  Unrecoverable errors during
 // the reading of the archive file should stop the process.
 
-static void fail(const char *msg, va_list ap) {
+static void fail_exit(const char *msg, va_list ap) {
   // This occurs very early during initialization: tty is not initialized.
   jio_fprintf(defaultStream::error_stream(),
               "An error has occurred while processing the"
@@ -90,7 +90,7 @@
 void FileMapInfo::fail_stop(const char *msg, ...) {
         va_list ap;
   va_start(ap, msg);
-  fail(msg, ap);        // Never returns.
+  fail_exit(msg, ap);   // Never returns.
   va_end(ap);           // for completeness.
 }
 
@@ -118,7 +118,7 @@
     tty->print_cr("]");
   } else {
     if (RequireSharedSpaces) {
-      fail(msg, ap);
+      fail_exit(msg, ap);
     } else {
       if (log_is_enabled(Info, cds)) {
         ResourceMark rm;
@@ -252,13 +252,15 @@
   _base_archive_is_default = false;
 }
 
-void SharedClassPathEntry::init(const char* name, bool is_modules_image, TRAPS) {
+void SharedClassPathEntry::init(bool is_modules_image,
+                                ClassPathEntry* cpe, TRAPS) {
   assert(DumpSharedSpaces || DynamicDumpSharedSpaces, "dump time only");
   _timestamp = 0;
   _filesize  = 0;
+  _from_class_path_attr = false;
 
   struct stat st;
-  if (os::stat(name, &st) == 0) {
+  if (os::stat(cpe->name(), &st) == 0) {
     if ((st.st_mode & S_IFMT) == S_IFDIR) {
       _type = dir_entry;
     } else {
@@ -268,6 +270,7 @@
       } else {
         _type = jar_entry;
         _timestamp = st.st_mtime;
+        _from_class_path_attr = cpe->from_class_path_attr();
       }
       _filesize = st.st_size;
     }
@@ -277,12 +280,12 @@
     //
     // If we can't access a jar file in the boot path, then we can't
     // make assumptions about where classes get loaded from.
-    FileMapInfo::fail_stop("Unable to open file %s.", name);
+    FileMapInfo::fail_stop("Unable to open file %s.", cpe->name());
   }
 
-  size_t len = strlen(name) + 1;
+  size_t len = strlen(cpe->name()) + 1;
   _name = MetadataFactory::new_array<char>(ClassLoaderData::the_null_class_loader_data(), (int)len, THREAD);
-  strcpy(_name->data(), name);
+  strcpy(_name->data(), cpe->name());
 }
 
 bool SharedClassPathEntry::validate(bool is_class_path) {
@@ -381,7 +384,7 @@
     const char* type = (is_jrt ? "jrt" : (cpe->is_jar_file() ? "jar" : "dir"));
     log_info(class, path)("add main shared path (%s) %s", type, cpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(cpe->name(), is_jrt, THREAD);
+    ent->init(is_jrt, cpe, THREAD);
     if (!is_jrt) {    // No need to do the modules image.
       EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
       update_shared_classpath(cpe, ent, THREAD);
@@ -397,7 +400,7 @@
   while (acpe != NULL) {
     log_info(class, path)("add app shared path %s", acpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(acpe->name(), false, THREAD);
+    ent->init(false, acpe, THREAD);
     EXCEPTION_MARK;
     update_shared_classpath(acpe, ent, THREAD);
     acpe = acpe->next();
@@ -409,7 +412,7 @@
   while (mpe != NULL) {
     log_info(class, path)("add module path %s",mpe->name());
     SharedClassPathEntry* ent = shared_path(i);
-    ent->init(mpe->name(), false, THREAD);
+    ent->init(false, mpe, THREAD);
     EXCEPTION_MARK;
     update_shared_classpath(mpe, ent, THREAD);
     mpe = mpe->next();
@@ -520,6 +523,182 @@
   }
 }
 
+char* FileMapInfo::skip_first_path_entry(const char* path) {
+  size_t path_sep_len = strlen(os::path_separator());
+  char* p = strstr((char*)path, os::path_separator());
+  if (p != NULL) {
+    debug_only( {
+      size_t image_name_len = strlen(MODULES_IMAGE_NAME);
+      assert(strncmp(p - image_name_len, MODULES_IMAGE_NAME, image_name_len) == 0,
+             "first entry must be the modules image");
+    } );
+    p += path_sep_len;
+  } else {
+    debug_only( {
+      assert(ClassLoader::string_ends_with(path, MODULES_IMAGE_NAME),
+             "first entry must be the modules image");
+    } );
+  }
+  return p;
+}
+
+int FileMapInfo::num_paths(const char* path) {
+  if (path == NULL) {
+    return 0;
+  }
+  int npaths = 1;
+  char* p = (char*)path;
+  while (p != NULL) {
+    char* prev = p;
+    p = strstr((char*)p, os::path_separator());
+    if (p != NULL) {
+      p++;
+      // don't count empty path
+      if ((p - prev) > 1) {
+       npaths++;
+      }
+    }
+  }
+  return npaths;
+}
+
+GrowableArray<char*>* FileMapInfo::create_path_array(const char* path) {
+  GrowableArray<char*>* path_array =  new(ResourceObj::RESOURCE_AREA, mtInternal)
+      GrowableArray<char*>(10);
+  char* begin_ptr = (char*)path;
+  char* end_ptr = strchr((char*)path, os::path_separator()[0]);
+  if (end_ptr == NULL) {
+    end_ptr = strchr((char*)path, '\0');
+  }
+  while (end_ptr != NULL) {
+    if ((end_ptr - begin_ptr) > 1) {
+      struct stat st;
+      char* temp_name = NEW_RESOURCE_ARRAY(char, (size_t)(end_ptr - begin_ptr + 1));
+      strncpy(temp_name, begin_ptr, end_ptr - begin_ptr);
+      temp_name[end_ptr - begin_ptr] = '\0';
+      if (os::stat(temp_name, &st) == 0) {
+        path_array->append(temp_name);
+      }
+    }
+    if (end_ptr < (path + strlen(path))) {
+      begin_ptr = ++end_ptr;
+      end_ptr = strchr(begin_ptr, os::path_separator()[0]);
+      if (end_ptr == NULL) {
+        end_ptr = strchr(begin_ptr, '\0');
+      }
+    } else {
+      break;
+    }
+  }
+  return path_array;
+}
+
+bool FileMapInfo::fail(const char* msg, const char* name) {
+  ClassLoader::trace_class_path(msg, name);
+  MetaspaceShared::set_archive_loading_failed();
+  return false;
+}
+
+bool FileMapInfo::check_paths(int shared_path_start_idx, int num_paths, GrowableArray<char*>* rp_array) {
+  int i = 0;
+  int j = shared_path_start_idx;
+  bool mismatch = false;
+  while (i < num_paths && !mismatch) {
+    while (shared_path(j)->from_class_path_attr()) {
+      // shared_path(j) was expanded from the JAR file attribute "Class-Path:"
+      // during dump time. It's not included in the -classpath VM argument.
+      j++;
+    }
+    if (!os::same_files(shared_path(j)->name(), rp_array->at(i))) {
+      mismatch = true;
+    }
+    i++;
+    j++;
+  }
+  return mismatch;
+}
+
+bool FileMapInfo::validate_boot_class_paths() {
+  //
+  // - Archive contains boot classes only - relaxed boot path check:
+  //   Extra path elements appended to the boot path at runtime are allowed.
+  //
+  // - Archive contains application or platform classes - strict boot path check:
+  //   Validate the entire runtime boot path, which must be compatible
+  //   with the dump time boot path. Appending boot path at runtime is not
+  //   allowed.
+  //
+
+  // The first entry in boot path is the modules_image (guaranteed by
+  // ClassLoader::setup_boot_search_path()). Skip the first entry. The
+  // path of the runtime modules_image may be different from the dump
+  // time path (e.g. the JDK image is copied to a different location
+  // after generating the shared archive), which is acceptable. For most
+  // common cases, the dump time boot path might contain modules_image only.
+  char* runtime_boot_path = Arguments::get_sysclasspath();
+  char* rp = skip_first_path_entry(runtime_boot_path);
+  assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
+  int dp_len = _header->_app_class_paths_start_index - 1; // ignore the first path to the module image
+  bool mismatch = false;
+
+  bool relaxed_check = !header()->has_platform_or_app_classes();
+  if (dp_len == 0 && rp == NULL) {
+    return true;   // ok, both runtime and dump time boot paths have modules_images only
+  } else if (dp_len == 0 && rp != NULL) {
+    if (relaxed_check) {
+      return true;   // ok, relaxed check, runtime has extra boot append path entries
+    } else {
+      mismatch = true;
+    }
+  } else if (dp_len > 0 && rp != NULL) {
+    int num;
+    ResourceMark rm;
+    GrowableArray<char*>* rp_array = create_path_array(rp);
+    int rp_len = rp_array->length();
+    if (rp_len >= dp_len) {
+      if (relaxed_check) {
+        // only check the leading entries in the runtime boot path, up to
+        // the length of the dump time boot path
+        num = dp_len;
+      } else {
+        // check the full runtime boot path, must match with dump time
+        num = rp_len;
+      }
+      mismatch = check_paths(1, num, rp_array);
+    }
+  }
+
+  if (mismatch) {
+    // The paths are different
+    return fail("[BOOT classpath mismatch, actual =", runtime_boot_path);
+  }
+  return true;
+}
+
+bool FileMapInfo::validate_app_class_paths(int shared_app_paths_len) {
+  const char *appcp = Arguments::get_appclasspath();
+  assert(appcp != NULL, "NULL app classpath");
+  int rp_len = num_paths(appcp);
+  bool mismatch = false;
+  if (rp_len < shared_app_paths_len) {
+    return fail("Run time APP classpath is shorter than the one at dump time: ", appcp);
+  }
+  if (shared_app_paths_len != 0 && rp_len != 0) {
+    // Prefix is OK: E.g., dump with -cp foo.jar, but run with -cp foo.jar:bar.jar.
+    ResourceMark rm;
+    GrowableArray<char*>* rp_array = create_path_array(appcp);
+    if (rp_array->length() == 0) {
+      // None of the jar file specified in the runtime -cp exists.
+      return fail("None of the jar file specified in the runtime -cp exists: -Djava.class.path=", appcp);
+    }
+    int j = _header->_app_class_paths_start_index;
+    mismatch = check_paths(j, shared_app_paths_len, rp_array);
+    if (mismatch) {
+      return fail("[APP classpath mismatch, actual: -Djava.class.path=", appcp);
+    }
+  }
+  return true;
+}
 
 bool FileMapInfo::validate_shared_path_table() {
   assert(UseSharedSpaces, "runtime only");
@@ -550,11 +729,16 @@
   }
 
   int module_paths_start_index = _header->_app_module_paths_start_index;
+  int shared_app_paths_len = 0;
 
   // validate the path entries up to the _max_used_path_index
   for (int i=0; i < _header->_max_used_path_index + 1; i++) {
     if (i < module_paths_start_index) {
       if (shared_path(i)->validate()) {
+        // Only count the app class paths not from the "Class-path" attribute of a jar manifest.
+        if (!shared_path(i)->from_class_path_attr() && i >= _header->_app_class_paths_start_index) {
+          shared_app_paths_len++;
+        }
         log_info(class, path)("ok");
       } else {
         if (_dynamic_archive_info != NULL && _dynamic_archive_info->_is_static) {
@@ -574,6 +758,16 @@
     }
   }
 
+  if (_header->_max_used_path_index == 0) {
+    // default archive only contains the module image in the bootclasspath
+    assert(shared_path(0)->is_modules_image(), "first shared_path must be the modules image");
+  } else {
+    if (!validate_boot_class_paths() || !validate_app_class_paths(shared_app_paths_len)) {
+      fail_continue("shared class paths mismatch (hint: enable -Xlog:class+path=info to diagnose the failure)");
+      return false;
+    }
+  }
+
   _validating_shared_path_table = false;
 
 #if INCLUDE_JVMTI
@@ -588,39 +782,6 @@
   return true;
 }
 
-bool FileMapInfo::same_files(const char* file1, const char* file2) {
-  if (strcmp(file1, file2) == 0) {
-    return true;
-  }
-
-  bool is_same = false;
-  // if the two paths diff only in case
-  struct stat st1;
-  struct stat st2;
-  int ret1;
-  int ret2;
-  ret1 = os::stat(file1, &st1);
-  ret2 = os::stat(file2, &st2);
-  if (ret1 < 0 || ret2 < 0) {
-    // one of the files is invalid. So they are not the same.
-    is_same = false;
-  } else if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
-    // different files
-    is_same = false;
-#ifndef _WINDOWS
-  } else if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) {
-    // same files
-    is_same = true;
-#else
-  } else if ((st1.st_size == st2.st_size) && (st1.st_ctime == st2.st_ctime) &&
-             (st1.st_mtime == st2.st_mtime)) {
-    // same files
-    is_same = true;
-#endif
-  }
-  return is_same;
-}
-
 bool FileMapInfo::check_archive(const char* archive_name, bool is_static) {
   int fd = os::open(archive_name, O_RDONLY | O_BINARY, 0);
   if (fd < 0) {
@@ -1749,7 +1910,7 @@
         jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
         THROW_MSG_(vmSymbols::java_io_IOException(), msg, NULL);
       } else {
-        ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, CHECK_NULL);
+        ent = ClassLoader::create_class_path_entry(path, &st, /*throw_exception=*/true, false, false, CHECK_NULL);
       }
     }
 
--- a/src/hotspot/share/memory/filemap.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/memory/filemap.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -53,13 +53,14 @@
   };
 protected:
   u1     _type;
+  bool   _from_class_path_attr;
   time_t _timestamp;          // jar timestamp,  0 if is directory, modules image or other
   long   _filesize;           // jar/jimage file size, -1 if is directory, -2 if other
   Array<char>* _name;
   Array<u1>*   _manifest;
 
 public:
-  void init(const char* name, bool is_modules_image, TRAPS);
+  void init(bool is_modules_image, ClassPathEntry* cpe, TRAPS);
   void metaspace_pointers_do(MetaspaceClosure* it);
   bool validate(bool is_class_path = true);
 
@@ -74,6 +75,7 @@
   void set_is_signed()     {
     _type = signed_jar_entry;
   }
+  bool from_class_path_attr() { return _from_class_path_attr; }
   time_t timestamp() const { return _timestamp; }
   long   filesize()  const { return _filesize; }
   const char* name() const { return _name->data(); }
@@ -240,7 +242,6 @@
   static bool get_base_archive_name_from_header(const char* archive_name,
                                                 int* size, char** base_archive_name);
   static bool check_archive(const char* archive_name, bool is_static);
-  static bool  same_files(const char* file1, const char* file2);
   void restore_shared_path_table();
   bool  init_from_file(int fd, bool is_static);
   static void metaspace_pointers_do(MetaspaceClosure* it);
@@ -376,6 +377,15 @@
   char* region_addr(int idx);
 
  private:
+  char* skip_first_path_entry(const char* path) NOT_CDS_RETURN_(NULL);
+  int   num_paths(const char* path) NOT_CDS_RETURN_(0);
+  GrowableArray<char*>* create_path_array(const char* path) NOT_CDS_RETURN_(NULL);
+  bool  fail(const char* msg, const char* name) NOT_CDS_RETURN_(FALSE);
+  bool  check_paths(int shared_path_start_idx,
+                    int num_paths,
+                    GrowableArray<char*>* rp_array) NOT_CDS_RETURN_(FALSE);
+  bool  validate_boot_class_paths() NOT_CDS_RETURN_(FALSE);
+  bool  validate_app_class_paths(int shared_app_paths_len) NOT_CDS_RETURN_(FALSE);
   bool  map_heap_data(MemRegion **heap_mem, int first, int max, int* num,
                       bool is_open = false) NOT_CDS_JAVA_HEAP_RETURN_(false);
   bool  region_crc_check(char* buf, size_t size, int expected_crc) NOT_CDS_RETURN_(false);
--- a/src/hotspot/share/opto/type.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/opto/type.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -730,8 +730,11 @@
   // Since we just discovered a new Type, compute its dual right now.
   assert( !_dual, "" );         // No dual yet
   _dual = xdual();              // Compute the dual
-  if( cmp(this,_dual)==0 ) {    // Handle self-symmetric
-    _dual = this;
+  if (cmp(this, _dual) == 0) {  // Handle self-symmetric
+    if (_dual != this) {
+      delete _dual;
+      _dual = this;
+    }
     return this;
   }
   assert( !_dual->_dual, "" );  // No reverse dual yet
--- a/src/hotspot/share/runtime/arguments.cpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/runtime/arguments.cpp	Fri Jun 28 16:49:32 2019 -0400
@@ -3571,7 +3571,7 @@
           "Cannot have more than 1 archive file specified in -XX:SharedArchiveFile during CDS dumping");
       }
       if (DynamicDumpSharedSpaces) {
-        if (FileMapInfo::same_files(SharedArchiveFile, ArchiveClassesAtExit)) {
+        if (os::same_files(SharedArchiveFile, ArchiveClassesAtExit)) {
           vm_exit_during_initialization(
             "Cannot have the same archive file specified for -XX:SharedArchiveFile and -XX:ArchiveClassesAtExit",
             SharedArchiveFile);
--- a/src/hotspot/share/runtime/os.hpp	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/hotspot/share/runtime/os.hpp	Fri Jun 28 16:49:32 2019 -0400
@@ -171,10 +171,6 @@
     init_globals_ext();
   }
 
-  // File names are case-insensitive on windows only
-  // Override me as needed
-  static int    file_name_strncmp(const char* s1, const char* s2, size_t num);
-
   // unset environment variable
   static bool unsetenv(const char* name);
 
@@ -544,6 +540,8 @@
 
   static int compare_file_modified_times(const char* file1, const char* file2);
 
+  static bool same_files(const char* file1, const char* file2);
+
   //File i/o operations
 
   static ssize_t read(int fd, void *buf, unsigned int nBytes);
--- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java	Fri Jun 28 16:49:32 2019 -0400
@@ -59,7 +59,6 @@
     private RequestPublishers() { }
 
     public static class ByteArrayPublisher implements BodyPublisher {
-        private volatile Flow.Publisher<ByteBuffer> delegate;
         private final int length;
         private final byte[] content;
         private final int offset;
@@ -99,7 +98,7 @@
         @Override
         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
             List<ByteBuffer> copy = copy(content, offset, length);
-            this.delegate = new PullPublisher<>(copy);
+            var delegate = new PullPublisher<>(copy);
             delegate.subscribe(subscriber);
         }
 
@@ -111,7 +110,6 @@
 
     // This implementation has lots of room for improvement.
     public static class IterablePublisher implements BodyPublisher {
-        private volatile Flow.Publisher<ByteBuffer> delegate;
         private final Iterable<byte[]> content;
         private volatile long contentLength;
 
@@ -174,7 +172,7 @@
         @Override
         public void subscribe(Flow.Subscriber<? super ByteBuffer> subscriber) {
             Iterable<ByteBuffer> iterable = this::iterator;
-            this.delegate = new PullPublisher<>(iterable);
+            var delegate = new PullPublisher<>(iterable);
             delegate.subscribe(subscriber);
         }
 
--- a/test/hotspot/jtreg/TEST.groups	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/TEST.groups	Fri Jun 28 16:49:32 2019 -0400
@@ -328,6 +328,7 @@
  -runtime/appcds/ExtraSymbols.java \
  -runtime/appcds/LongClassListPath.java \
  -runtime/appcds/LotsOfClasses.java \
+ -runtime/appcds/RelativePath.java \
  -runtime/appcds/SharedArchiveConsistency.java \
  -runtime/appcds/UnusedCPDuringDump.java \
  -runtime/appcds/VerifierTest_1B.java
--- a/test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/AppCDSOptions.java	Fri Jun 28 16:49:32 2019 -0400
@@ -28,9 +28,15 @@
 
 public class AppCDSOptions extends CDSOptions {
     public String appJar;
+    public String appJarDir;
 
     public AppCDSOptions setAppJar(String appJar) {
         this.appJar = appJar;
         return this;
     }
+
+    public AppCDSOptions setAppJarDir(String appJarDir) {
+        this.appJarDir = appJarDir;
+        return this;
+    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/AppendClasspath.java	Fri Jun 28 16:49:32 2019 -0400
@@ -36,6 +36,9 @@
  */
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
 import jdk.test.lib.process.OutputAnalyzer;
 
 public class AppendClasspath {
@@ -53,9 +56,24 @@
         "HelloMore")
       .assertNormalExit();
 
+    // PASS: 2) runtime has an non-existing jar in the -cp
+    String classDir = System.getProperty("test.classes");
+    String newFile = "non-exist.jar";
+    String nonExistPath = classDir + File.separator + newFile;
+    String classPath = appJar + File.pathSeparator + nonExistPath;
+    File nonExistJar = new File(classDir, newFile);
+    if (nonExistJar.exists()) {
+        nonExistJar.delete();
+    }
+    TestCommon.run(
+        "-cp", classPath,
+        "-Xlog:class+path=trace",
+        "Hello")
+      .assertNormalExit();
+
     final String errorMessage1 = "Unable to use shared archive";
     final String errorMessage2 = "shared class paths mismatch";
-    // FAIL: 2) runtime with classpath different from the one used in dump time
+    // FAIL: 1) runtime with classpath different from the one used in dump time
     // (runtime has an extra jar file prepended to the class path)
     TestCommon.run(
         "-Xlog:cds",
@@ -63,7 +81,7 @@
         "HelloMore")
         .assertAbnormalExit(errorMessage1, errorMessage2);
 
-    // FAIL: 3) runtime with classpath part of the one used in dump time
+    // FAIL: 2) runtime with classpath part of the one used in dump time
     TestCommon.testDump(appJar + File.pathSeparator + appJar2,
                                       TestCommon.list("Hello"));
     TestCommon.run(
@@ -72,12 +90,26 @@
         "Hello")
         .assertAbnormalExit(errorMessage1, errorMessage2);
 
-    // FAIL: 4) runtime with same set of jar files in the classpath but
+    // FAIL: 3) runtime with same set of jar files in the classpath but
     // with different order
     TestCommon.run(
         "-Xlog:cds",
         "-cp", appJar2 + File.pathSeparator + appJar,
         "HelloMore")
         .assertAbnormalExit(errorMessage1, errorMessage2);
-  }
+
+    // FAIL: 4) non-existing jar during dump time but jar exists during runtime
+    TestCommon.testDump(classPath, TestCommon.list("Hello"));
+
+    Files.copy(Paths.get(classDir, "hello.jar"),
+        Paths.get(classDir, newFile),
+        StandardCopyOption.REPLACE_EXISTING);
+
+    TestCommon.run(
+        "-cp", classPath,
+        "-Xlog:class+path=trace",
+        "Hello")
+        .assertAbnormalExit(errorMessage1, errorMessage2);
+
+    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/BootClassPathMismatch.java	Fri Jun 28 16:49:32 2019 -0400
@@ -34,6 +34,7 @@
  * @run driver BootClassPathMismatch
  */
 
+import jdk.test.lib.Platform;
 import jdk.test.lib.cds.CDSOptions;
 import jdk.test.lib.cds.CDSTestUtils;
 import jdk.test.lib.process.OutputAnalyzer;
@@ -41,7 +42,9 @@
 import java.nio.file.Files;
 import java.nio.file.FileAlreadyExistsException;
 import java.nio.file.StandardCopyOption;
+import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.nio.file.attribute.FileTime;
 
 
 public class BootClassPathMismatch {
@@ -126,6 +129,55 @@
                 "-cp", appJar, "-verbose:class",
                 "-Xbootclasspath/a:" + appJar, "Hello")
             .assertNormalExit("[class,load] Hello source: shared objects file");
+
+        // test relative path to appJar
+        String newJar = TestCommon.composeRelPath(appJar);
+        TestCommon.run(
+                "-cp", newJar, "-verbose:class",
+                "-Xbootclasspath/a:" + newJar, "Hello")
+            .assertNormalExit("[class,load] Hello source: shared objects file");
+
+        int idx = appJar.lastIndexOf(File.separator);
+        String jarName = appJar.substring(idx + 1);
+        String jarDir = appJar.substring(0, idx);
+        // relative path starting with "."
+        TestCommon.runWithRelativePath(
+            jarDir,
+            "-Xshare:on",
+            "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+            "-cp", "." + File.separator + jarName,
+            "-Xbootclasspath/a:" + "." + File.separator + jarName,
+            "-Xlog:class+load=trace,class+path=info",
+            "Hello")
+            .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+                });
+
+        // relative path starting with ".."
+        idx = jarDir.lastIndexOf(File.separator);
+        String jarSubDir = jarDir.substring(idx + 1);
+        TestCommon.runWithRelativePath(
+            jarDir,
+            "-Xshare:on",
+            "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+            "-cp", ".." + File.separator + jarSubDir + File.separator + jarName,
+            "-Xbootclasspath/a:" + ".." + File.separator + jarSubDir + File.separator + jarName,
+            "-Xlog:class+load=trace,class+path=info",
+            "Hello")
+            .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+                });
+
+        // test sym link to appJar
+        if (!Platform.isWindows()) {
+            File linkedJar = TestCommon.createSymLink(appJar);
+            TestCommon.run(
+                    "-cp", linkedJar.getPath(), "-verbose:class",
+                    "-Xbootclasspath/a:" + linkedJar.getPath(), "Hello")
+                .assertNormalExit("[class,load] Hello source: shared objects file");
+        }
     }
 
     /* Archive contains boot classes only, runtime add -Xbootclasspath/a path.
@@ -158,6 +210,12 @@
                 "-Xlog:cds",
                 "-cp", appJar, "-Xbootclasspath/a:" + appJar, "Hello")
             .assertAbnormalExit(mismatchMessage);
+
+        // test relative path to appJar
+        String newJar = TestCommon.composeRelPath(appJar);
+        TestCommon.run(
+                "-cp", newJar, "-Xbootclasspath/a:" + newJar, "Hello")
+            .assertAbnormalExit(mismatchMessage);
     }
 
     private static void copyHelloToNewDir() throws Exception {
@@ -168,13 +226,25 @@
         } catch (FileAlreadyExistsException e) { }
 
         // copy as hello.jar
+        Path dstPath = Paths.get(dstDir, "hello.jar");
         Files.copy(Paths.get(classDir, "hello.jar"),
-            Paths.get(dstDir, "hello.jar"),
+            dstPath,
             StandardCopyOption.REPLACE_EXISTING);
 
+        File helloJar = dstPath.toFile();
+        long modTime = helloJar.lastModified();
+
         // copy as hello.jar1
+        Path dstPath2 = Paths.get(dstDir, "hello.jar1");
         Files.copy(Paths.get(classDir, "hello.jar"),
-            Paths.get(dstDir, "hello.jar1"),
+            dstPath2,
             StandardCopyOption.REPLACE_EXISTING);
+
+        // On Windows, we rely on the file size, creation time, and
+        // modification time in order to differentiate between 2 files.
+        // Setting a different modification time on hello.jar1 so that this test
+        // runs more reliably on Windows.
+        modTime += 10000;
+        Files.setAttribute(dstPath2, "lastModifiedTime", FileTime.fromMillis(modTime));
     }
 }
--- a/test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/PrintSharedArchiveAndExit.java	Fri Jun 28 16:49:32 2019 -0400
@@ -105,12 +105,13 @@
         "-XX:+PrintSharedArchiveAndExit")
       .ifNoMappingFailure(output -> check(output, 1, true, lastCheckMsg, "Run time APP classpath is shorter than the one at dump time: ."));
 
-    log("Use an invalid App CP -- all the JAR paths should be checked");
+    log("Use an invalid App CP -- all the JAR paths should be checked.\n" +
+        "Non-existing jar files will be ignored.");
     String invalidCP = "non-existing-dir" + File.pathSeparator + cp;
     TestCommon.run(
         "-cp", invalidCP,
         "-XX:+PrintSharedArchiveAndExit")
-      .ifNoMappingFailure(output -> check(output, 1, true, lastCheckMsg, "APP classpath mismatch, actual: -Djava.class.path=" + invalidCP));
+      .ifNoMappingFailure(output -> check(output, 0, true, lastCheckMsg));
 
     log("Changed modification time of hello.jar -- all the JAR paths should be checked");
     (new File(appJar)).setLastModified(System.currentTimeMillis() + 2000);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/RelativePath.java	Fri Jun 28 16:49:32 2019 -0400
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test relative paths specified in the -cp.
+ * @requires vm.cds
+ * @library /test/lib
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @compile test-classes/Hello.java
+ * @compile test-classes/HelloMore.java
+ * @run driver RelativePath
+ */
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES;
+import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
+import java.util.Arrays;
+import jdk.test.lib.Platform;
+
+public class RelativePath {
+
+  private static final Path USER_DIR = Paths.get(System.getProperty("user.dir"));
+
+  public static void main(String[] args) throws Exception {
+    String appJar = JarBuilder.getOrCreateHelloJar();
+    String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore");
+
+    // dump an archive with only the jar name in the -cp
+    int idx = appJar.lastIndexOf(File.separator);
+    String jarName = appJar.substring(idx + 1);
+    String jarDir = appJar.substring(0, idx);
+    TestCommon.testDump(jarDir, jarName, TestCommon.list("Hello"));
+
+    // copy the jar file to another dir. Specify the jar file without
+    // a directory path.
+    Path srcPath = Paths.get(appJar);
+    Path destDir = Files.createTempDirectory(USER_DIR, "deploy");
+    Path destPath = destDir.resolve(jarName);
+    Files.copy(srcPath, destPath, REPLACE_EXISTING, COPY_ATTRIBUTES);
+    TestCommon.runWithRelativePath(
+        destDir.toString(),
+        "-Xshare:on",
+        "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+        "-cp", jarName + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // Long path test
+    // Create a long directory path and copy the appJar there.
+    final int MAX_PATH = 260;
+    destDir = Paths.get(jarDir);
+    int subDirLen = MAX_PATH - jarDir.length() - 3;
+    if (subDirLen > 0) {
+        char[] chars = new char[subDirLen];
+        Arrays.fill(chars, 'x');
+        String subPath = new String(chars);
+        destDir = Paths.get(jarDir, subPath);
+    }
+    File longDir = destDir.toFile();
+    longDir.mkdir();
+    String destJar = longDir.getPath() + File.separator + jarName;
+    Files.copy(Paths.get(appJar), Paths.get(destJar), REPLACE_EXISTING);
+    // Create an archive with the appJar in the long directory path.
+    TestCommon.testDump(destJar, TestCommon.list("Hello"));
+
+    // Run with -cp containing the appJar and another jar appended.
+    TestCommon.run(
+        "-cp", destJar + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // Dump an archive with a specified JAR file in -classpath
+    TestCommon.testDump(appJar, TestCommon.list("Hello"));
+
+    // compose a relative path to the hello.jar
+    String newHello = TestCommon.composeRelPath(appJar);
+
+    // create a sym link to the original hello.jar
+    File linkedHello = null;
+    if (!Platform.isWindows()) {
+        linkedHello = TestCommon.createSymLink(appJar);
+    }
+
+    // PASS:1) same appJar but referred to via a relative path
+    TestCommon.run(
+        "-cp", newHello + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+      .assertNormalExit();
+
+    // PASS:2) relative path starting with "."
+    TestCommon.runWithRelativePath(
+        jarDir,
+        "-Xshare:on",
+        "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+        "-cp", "." + File.separator + jarName + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // PASS:3) relative path starting with ".."
+    idx = jarDir.lastIndexOf(File.separator);
+    String jarSubDir = jarDir.substring(idx + 1);
+    TestCommon.runWithRelativePath(
+        jarDir,
+        "-Xshare:on",
+        "-XX:SharedArchiveFile=" + TestCommon.getCurrentArchiveName(),
+        "-cp", ".." + File.separator + jarSubDir + File.separator + jarName
+               + File.pathSeparator + appJar2,
+        "-Xlog:class+load=trace,class+path=info",
+        "HelloMore")
+        .assertNormalExit(output -> {
+                output.shouldContain("Hello source: shared objects file")
+                      .shouldHaveExitValue(0);
+            });
+
+    // PASS:4) a jar linked to the original hello.jar
+    if (!Platform.isWindows()) {
+        TestCommon.run(
+            "-cp", linkedHello.getPath() + File.pathSeparator + appJar2,
+            "HelloMore")
+          .assertNormalExit();
+    }
+
+    final String errorMessage1 = "Unable to use shared archive";
+    final String errorMessage2 = "shared class paths mismatch";
+    // FAIL: 1) runtime with classpath different from the one used in dump time
+    // (runtime has an extra jar file prepended to the class path)
+    TestCommon.run(
+        "-cp", appJar2 + File.pathSeparator + newHello,
+        "HelloMore")
+        .assertAbnormalExit(errorMessage1, errorMessage2);
+
+    }
+}
--- a/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/TestCommon.java	Fri Jun 28 16:49:32 2019 -0400
@@ -128,6 +128,10 @@
         return createArchive(appJar, classList, suffix);
     }
 
+    public static OutputAnalyzer dump(String appJarDir, String appJar, String classList[],
+                                               String... suffix) throws Exception {
+        return createArchive(appJarDir, appJar, classList, suffix);
+    }
 
     // Create AppCDS archive using most common args - convenience method
     public static OutputAnalyzer createArchive(String appJar, String classList[],
@@ -138,6 +142,15 @@
         return createArchive(opts);
     }
 
+    public static OutputAnalyzer createArchive(String appJarDir, String appJar, String classList[],
+                                               String... suffix) throws Exception {
+        AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
+        opts.setAppJarDir(appJarDir);
+        opts.setClassList(classList);
+        opts.addSuffix(suffix);
+        return createArchive(opts);
+    }
+
     // Simulate -Xshare:dump with -XX:ArchiveClassesAtExit. See comments around patchJarForDynamicDump()
     private static final Class tmp = DynamicDumpHelper.class;
 
@@ -222,6 +235,9 @@
 
         String[] cmdLine = cmd.toArray(new String[cmd.size()]);
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
+        if (opts.appJarDir != null) {
+            pb.directory(new File(opts.appJarDir));
+        }
         return executeAndLog(pb, "dump");
     }
 
@@ -360,6 +376,9 @@
 
         String[] cmdLine = cmd.toArray(new String[cmd.size()]);
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
+        if (opts.appJarDir != null) {
+            pb.directory(new File(opts.appJarDir));
+        }
         return executeAndLog(pb, "exec");
     }
 
@@ -378,6 +397,13 @@
         return new Result(opts, runWithArchive(opts));
     }
 
+    public static Result runWithRelativePath(String jarDir, String... suffix) throws Exception {
+        AppCDSOptions opts = (new AppCDSOptions());
+        opts.setAppJarDir(jarDir);
+        opts.addSuffix(suffix);
+        return new Result(opts, runWithArchive(opts));
+    }
+
     public static OutputAnalyzer exec(String appJar, String... suffix) throws Exception {
         AppCDSOptions opts = (new AppCDSOptions()).setAppJar(appJar);
         opts.addSuffix(suffix);
@@ -443,6 +469,20 @@
         return output;
     }
 
+    public static OutputAnalyzer testDump(String appJarDir, String appJar, String classList[],
+                                          String... suffix) throws Exception {
+        OutputAnalyzer output = dump(appJarDir, appJar, classList, suffix);
+        if (DYNAMIC_DUMP) {
+            if (isUnableToMap(output)) {
+                throw new SkippedException(UnableToMapMsg);
+            }
+            output.shouldContain("Written dynamic archive");
+        } else {
+            output.shouldContain("Loading classes to share");
+        }
+        output.shouldHaveExitValue(0);
+        return output;
+    }
 
     /**
      * Simple test -- dump and execute appJar with the given classList in classlist.
@@ -590,4 +630,32 @@
             }
         }
     }
+
+    public static String composeRelPath(String appJar) {
+         int idx = appJar.lastIndexOf(File.separator);
+         String jarName = appJar.substring(idx + 1);
+         String jarDir = appJar.substring(0, idx);
+         String lastDir = jarDir.substring(jarDir.lastIndexOf(File.separator));
+         String relPath = jarDir + File.separator + ".." + File.separator + lastDir;
+         String newJar = relPath + File.separator + jarName;
+         return newJar;
+    }
+
+
+    public static File createSymLink(String appJar) throws Exception {
+         int idx = appJar.lastIndexOf(File.separator);
+         String jarName = appJar.substring(idx + 1);
+         String jarDir = appJar.substring(0, idx);
+         File origJar = new File(jarDir, jarName);
+         String linkedJarName = "linked_" + jarName;
+         File linkedJar = null;
+         if (!Platform.isWindows()) {
+             linkedJar = new File(jarDir, linkedJarName);
+             if (linkedJar.exists()) {
+                 linkedJar.delete();
+             }
+             Files.createSymbolicLink(linkedJar.toPath(), origJar.toPath());
+         }
+         return linkedJar;
+    }
 }
--- a/test/hotspot/jtreg/runtime/appcds/dynamicArchive/DynamicArchiveTestBase.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/hotspot/jtreg/runtime/appcds/dynamicArchive/DynamicArchiveTestBase.java	Fri Jun 28 16:49:32 2019 -0400
@@ -108,7 +108,7 @@
             cmdLine = TestCommon.concat(cmdLine, "-XX:SharedArchiveFile=" + baseArchiveName);
         }
         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
-        return execProcess("dump", cmdLine);
+        return execProcess("dump", null, cmdLine);
     }
 
     public static Result dump2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
@@ -188,7 +188,23 @@
             "-Xshare:on",
             "-XX:SharedArchiveFile=" + archiveFiles);
         cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
-        return execProcess("exec", cmdLine);
+        return execProcess("exec", null, cmdLine);
+    }
+
+    public static Result runWithRelativePath(String baseArchiveName, String topArchiveName,
+                              String jarDir, String ... cmdLineSuffix)
+        throws Exception {
+        if (baseArchiveName == null && topArchiveName == null) {
+            throw new RuntimeException("Both baseArchiveName and topArchiveName cannot be null at the same time.");
+        }
+        String archiveFiles = (baseArchiveName == null) ? topArchiveName :
+            (topArchiveName == null) ? baseArchiveName :
+            baseArchiveName + File.pathSeparator + topArchiveName;
+        String[] cmdLine = TestCommon.concat(
+            "-Xshare:on",
+            "-XX:SharedArchiveFile=" + archiveFiles);
+        cmdLine = TestCommon.concat(cmdLine, cmdLineSuffix);
+        return execProcess("exec", jarDir, cmdLine);
     }
 
     public static Result run2_WB(String baseArchiveName, String topArchiveName, String ... cmdLineSuffix)
@@ -221,11 +237,14 @@
    }
 
 
-    private static Result execProcess(String mode, String[] cmdLine) throws Exception {
+    private static Result execProcess(String mode, String jarDir, String[] cmdLine) throws Exception {
         if (!executedIn_run) {
             throw new Exception("Test error: dynamic archive tests must be executed via DynamicArchiveTestBase.run()");
         }
         ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(true, cmdLine);
+        if (jarDir != null) {
+            pb.directory(new File(jarDir));
+        }
         OutputAnalyzer output = TestCommon.executeAndLog(pb, mode);
         CDSOptions opts = new CDSOptions();
         String xShareMode = getXshareMode(cmdLine);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/appcds/dynamicArchive/RelativePath.java	Fri Jun 28 16:49:32 2019 -0400
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+/*
+ * @test
+ * @summary Test relative paths specified in the -cp.
+ * @requires vm.cds
+ * @library /test/lib /test/hotspot/jtreg/runtime/appcds
+ * @modules java.base/jdk.internal.misc
+ *          java.management
+ *          jdk.jartool/sun.tools.jar
+ * @compile ../test-classes/Hello.java
+ * @compile ../test-classes/HelloMore.java
+ * @run driver RelativePath
+ */
+
+import java.io.File;
+
+public class RelativePath extends DynamicArchiveTestBase {
+
+    public static void main(String[] args) throws Exception {
+        runTest(AppendClasspath::testDefaultBase);
+    }
+
+    static void testDefaultBase() throws Exception {
+        String topArchiveName = getNewArchiveName("top");
+        doTest(topArchiveName);
+    }
+
+    private static void doTest(String topArchiveName) throws Exception {
+        String appJar = JarBuilder.getOrCreateHelloJar();
+        String appJar2 = JarBuilder.build("AppendClasspath_HelloMore", "HelloMore");
+
+        int idx = appJar.lastIndexOf(File.separator);
+        String jarName = appJar.substring(idx + 1);
+        String jarDir = appJar.substring(0, idx);
+        // relative path starting with "."
+        runWithRelativePath(null, topArchiveName, jarDir,
+            "-Xlog:class+load",
+            "-Xlog:cds+dynamic=debug,cds=debug",
+            "-cp", "." + File.separator + "hello.jar" + File.pathSeparator + appJar2,
+            "HelloMore")
+            .assertNormalExit(output -> {
+                    output.shouldContain("Hello source: shared objects file")
+                          .shouldContain("Hello World ... More")
+                          .shouldHaveExitValue(0);
+                });
+
+        // relative path starting with ".."
+        idx = jarDir.lastIndexOf(File.separator);
+        String jarSubDir = jarDir.substring(idx + 1);
+        runWithRelativePath(null, topArchiveName, jarDir,
+            "-Xlog:class+load",
+            "-Xlog:cds+dynamic=debug,cds=debug",
+            "-cp",
+            ".." + File.separator + jarSubDir + File.separator + "hello.jar" + File.pathSeparator + appJar2,
+            "HelloMore")
+            .assertNormalExit(output -> {
+                    output.shouldContain("Hello source: shared objects file")
+                          .shouldContain("Hello World ... More")
+                          .shouldHaveExitValue(0);
+                });
+
+    }
+}
--- a/test/jdk/java/net/HttpCookie/IllegalCookieNameTest.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/java/net/HttpCookie/IllegalCookieNameTest.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2019, 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,25 +23,35 @@
 
 /* @test
  * @bug 7183292
+ * @library /test/lib
  * @modules jdk.httpserver
+ * @run main IllegalCookieNameTest
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true IllegalCookieNameTest
  */
 import java.net.*;
 import java.util.*;
 import java.io.*;
 import com.sun.net.httpserver.*;
+import jdk.test.lib.net.URIBuilder;
 
 public class IllegalCookieNameTest {
-    public static void main(String[] args) throws IOException {
+    public static void main(String[] args) throws Exception {
         HttpServer s = null;
         try {
-            InetSocketAddress addr = new InetSocketAddress(0);
+            InetAddress loopback = InetAddress.getLoopbackAddress();
+            InetSocketAddress addr = new InetSocketAddress(loopback, 0);
             s = HttpServer.create(addr, 10);
             s.createContext("/", new HHandler());
             s.start();
-            String u = "http://127.0.0.1:" + s.getAddress().getPort() + "/";
+            String u = URIBuilder.newBuilder()
+                .scheme("http")
+                .loopback()
+                .port(s.getAddress().getPort())
+                .path("/")
+                .build().toString();
             CookieHandler.setDefault(new TestCookieHandler());
             URL url = new URL(u);
-            HttpURLConnection c = (HttpURLConnection) url.openConnection();
+            HttpURLConnection c = (HttpURLConnection) url.openConnection(Proxy.NO_PROXY);
             c.getHeaderFields();
             System.out.println ("OK");
         } finally {
--- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTest.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2019, 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
@@ -258,14 +258,27 @@
     public static URL url(HttpProtocolType protocol, InetSocketAddress address,
                           String path) throws MalformedURLException {
         return new URL(protocol(protocol),
-                       address.getHostString(),
+                       address.getAddress().getHostAddress(),
                        address.getPort(), path);
     }
 
     public static Proxy proxy(HTTPTestServer server, HttpAuthType authType) {
-        return (authType == HttpAuthType.PROXY)
-               ? new Proxy(Proxy.Type.HTTP, server.getAddress())
-               : null;
+        if (authType != HttpAuthType.PROXY) return null;
+
+        InetSocketAddress proxyAddress = server.getProxyAddress();
+        if (!proxyAddress.isUnresolved()) {
+            // Forces the proxy to use an unresolved address created
+            // from the actual IP address to avoid using the proxy
+            // address hostname which would result in resolving to
+            // a posibly different address. For instance we want to
+            // avoid cases such as:
+            //    ::1 => "localhost" => 127.0.0.1
+            proxyAddress = InetSocketAddress.
+                createUnresolved(proxyAddress.getAddress().getHostAddress(),
+                                 proxyAddress.getPort());
+        }
+
+        return new Proxy(Proxy.Type.HTTP, proxyAddress);
     }
 
     public static HttpURLConnection openConnection(URL url,
--- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestServer.java	Fri Jun 28 16:49:32 2019 -0400
@@ -391,6 +391,10 @@
         return serverImpl.getAddress();
     }
 
+    public InetSocketAddress getProxyAddress() {
+        return serverImpl.getAddress();
+    }
+
     public void stop() {
         serverImpl.stop(0);
         if (redirect != null) {
@@ -1019,7 +1023,7 @@
         }
 
         @Override
-        public InetSocketAddress getAddress() {
+        public InetSocketAddress getProxyAddress() {
             return new InetSocketAddress(ss.getInetAddress(), ss.getLocalPort());
         }
 
@@ -1047,7 +1051,7 @@
             Socket clientConnection = null;
             try {
                 while (true) {
-                    System.out.println("Tunnel: Waiting for client");
+                    System.out.println("Tunnel: Waiting for client at: " + ss);
                     Socket previous = clientConnection;
                     try {
                         clientConnection = ss.accept();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/net/httpclient/ByteArrayPublishers.java	Fri Jun 28 16:49:32 2019 -0400
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test
+ * @bug 8222968
+ * @summary ByteArrayPublisher is not thread-safe resulting in broken re-use of HttpRequests
+ * @run main/othervm ByteArrayPublishers
+ */
+
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.util.ArrayList;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.CompletableFuture;
+
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpServer;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.charset.StandardCharsets;
+import static java.net.http.HttpRequest.BodyPublisher;
+import static java.net.http.HttpRequest.BodyPublishers;
+
+public class ByteArrayPublishers {
+    private static final BodyPublisher BODY_PUBLISHER =
+        BodyPublishers.ofByteArray("abcdefghijklmnopqrstuvwxyz".getBytes());
+
+    static int LOOPS = 100;
+
+    public static void main(String[] args) throws Exception {
+        HttpServer server = null;
+        try {
+            InetAddress loopBack = InetAddress.getLoopbackAddress();
+            String lpBackStr = loopBack.getHostAddress();
+            InetSocketAddress serverAddr = new InetSocketAddress(loopBack, 0);
+            server = HttpServer.create(serverAddr, 500);
+            server.createContext("/", (HttpExchange e) -> {
+                    e.getRequestBody().readAllBytes();
+                    String response = "Hello world";
+                    e.sendResponseHeaders(200, response.length());
+                    e.getResponseBody().write(response.getBytes(StandardCharsets.ISO_8859_1));
+                    e.close();
+            });
+            server.start();
+            var address = server.getAddress();
+            URI dest = new URI("http://" + lpBackStr + ":"
+                + Integer.toString(address.getPort()) + "/");
+
+            HttpClient client = createClient();
+
+            ArrayList<CompletableFuture<HttpResponse<Void>>> futures = new ArrayList<>(LOOPS);
+            LinkedBlockingQueue<Object> results = new LinkedBlockingQueue<Object>();
+            for (int i=0;i<LOOPS;i++) {
+                futures.add(
+                    client.sendAsync(createRequest(dest), HttpResponse.BodyHandlers.discarding())
+                          .handle((v, t) -> {
+                                if (t != null)
+                                    results.add(t);
+                                else
+                                    results.add(v);
+                                return null;
+                          }));
+            }
+
+            for (int i=0; i<LOOPS; i++) {
+                Object o = results.take();
+                if (o instanceof Exception) {
+                    throw new RuntimeException((Exception)o);
+                }
+            }
+        } finally {
+            server.stop(1);
+        }
+    }
+
+    private static HttpRequest createRequest(URI uri) throws URISyntaxException {
+        HttpRequest.Builder builder = HttpRequest.newBuilder(uri)
+                .method("POST", BODY_PUBLISHER)
+                .version(HttpClient.Version.HTTP_1_1);
+        builder.header("content-type", "text/plain");
+        return builder.build();
+    }
+
+    private static HttpClient createClient() {
+        return HttpClient.newBuilder()
+                .version(HttpClient.Version.HTTP_1_1)
+                .build();
+
+    }
+}
--- a/test/jdk/java/nio/channels/Selector/RacyDeregister.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/java/nio/channels/Selector/RacyDeregister.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, 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,11 +41,6 @@
  */
 public class RacyDeregister {
 
-    // FIXME: NUM_OUTER_LOOP_ITERATIONS should be reverted to the hard-coded
-    // value 15 when JDK-8161083 is resolved as either a bug or a non-issue.
-    static final int NUM_OUTER_LOOP_ITERATIONS =
-        System.getProperty("os.name").startsWith("Windows") ? 150 : 15;
-
     // 90% of 1200 second timeout as milliseconds
     static final int TIMEOUT_THRESHOLD_MILLIS = 1200*900;
 
@@ -90,7 +85,7 @@
 
             public void run() {
                 try {
-                    for (int k = 0; k < NUM_OUTER_LOOP_ITERATIONS; k++) {
+                    for (int k = 0; k < 15; k++) {
                         System.out.format("outer loop %3d at %7d ms%n", k,
                             System.currentTimeMillis() - t0);
                         System.out.flush();
--- a/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/ftp/FtpURLConnectionLeak.java	Fri Jun 28 16:49:32 2019 -0400
@@ -27,7 +27,7 @@
  * @summary FtpURLConnection doesn't close FTP connection when FileNotFoundException is thrown
  * @library ../www/ftptest/
  * @build FtpServer FtpCommandHandler FtpAuthHandler FtpFileSystemHandler
- * @run main FtpURLConnectionLeak
+ * @run main/othervm FtpURLConnectionLeak
  */
 import java.io.FileNotFoundException;
 import java.io.InputStream;
--- a/test/jdk/sun/net/www/http/HttpClient/RetryPost.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/http/HttpClient/RetryPost.java	Fri Jun 28 16:49:32 2019 -0400
@@ -54,23 +54,19 @@
     MyHandler httpHandler;
     ExecutorService executorService;
 
-    public static void main(String[] args) {
+    public static void main(String[] args) throws Exception {
         if (args.length == 1 && args[0].equals("noRetry"))
             shouldRetry = false;
 
         new RetryPost();
     }
 
-    public RetryPost() {
-        try {
-            startHttpServer(shouldRetry);
-            doClient();
-        } catch (IOException ioe) {
-            System.err.println(ioe);
-        }
+    public RetryPost() throws Exception {
+        startHttpServer(shouldRetry);
+        doClient();
     }
 
-    void doClient() {
+    void doClient() throws Exception {
         try {
             InetSocketAddress address = httpServer.getAddress();
             URL url = URIBuilder.newBuilder()
@@ -95,8 +91,6 @@
             else if (!shouldRetry && httpHandler.getCallCount() != 1)
                 throw new RuntimeException("Failed: Handler should have only been called once" +
                                            "It was called "+ httpHandler.getCallCount() + " times");
-        } catch (IOException e) {
-            e.printStackTrace();
         } finally {
             httpServer.stop(1);
             executorService.shutdown();
@@ -119,8 +113,8 @@
     }
 
     class MyHandler implements HttpHandler {
-        int callCount = 0;
-        boolean shouldRetry;
+        volatile int callCount = 0;
+        final boolean shouldRetry;
 
         public MyHandler(boolean shouldRetry) {
             this.shouldRetry = shouldRetry;
--- a/test/jdk/sun/net/www/protocol/http/B5017051.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/B5017051.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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,7 +25,9 @@
  * @test
  * @bug 5017051 6360774
  * @modules jdk.httpserver
+ * @library /test/lib
  * @run main/othervm B5017051
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B5017051
  * @summary Tests CR 5017051 & 6360774
  */
 
@@ -35,6 +37,7 @@
 import com.sun.net.httpserver.*;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
+import jdk.test.lib.net.URIBuilder;
 
 /*
  * Part 1:
@@ -55,42 +58,47 @@
 
 public class B5017051
 {
-    com.sun.net.httpserver.HttpServer httpServer;
+    HttpServer httpServer;
     ExecutorService executorService;
 
-    public static void main(String[] args)
-    {
+    public static void main(String[] args) throws Exception {
         new B5017051();
     }
 
-    public B5017051()
-    {
-        try {
-            startHttpServer();
-            doClient();
-        } catch (IOException ioe) {
-            System.err.println(ioe);
-        }
+    public B5017051() throws Exception {
+        startHttpServer();
+        doClient();
     }
 
-    void doClient() {
+    void doClient() throws Exception {
         java.net.Authenticator.setDefault(new MyAuthenticator());
         CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
+        ProxySelector.setDefault(ProxySelector.of(null));
 
         try {
             InetSocketAddress address = httpServer.getAddress();
 
             // Part 1
-            URL url = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test/");
+            URL url = URIBuilder.newBuilder()
+                .scheme("http")
+                .host(address.getAddress())
+                .port(address.getPort())
+                .path("/test/")
+                .toURL();
             HttpURLConnection uc = (HttpURLConnection)url.openConnection();
             int resp = uc.getResponseCode();
             if (resp != 200)
-                throw new RuntimeException("Failed: Part 1, Response code is not 200");
+                throw new RuntimeException("Failed: Part 1, Response code is not 200: " + resp);
 
             System.out.println("Response code from Part 1 = 200 OK");
 
             // Part 2
-            URL url2 = new URL("http://" + address.getHostName() + ":" + address.getPort() + "/test2/");
+            URL url2 = URIBuilder.newBuilder()
+                .scheme("http")
+                .host(address.getAddress())
+                .port(address.getPort())
+                .path("/test2/")
+                .toURL();
 
             // can use the global CookieHandler used for the first test as the URL's are different
             CookieHandler ch = CookieHandler.getDefault();
@@ -106,15 +114,10 @@
             uc = (HttpURLConnection)url2.openConnection();
             resp = uc.getResponseCode();
             if (resp != 200)
-                throw new RuntimeException("Failed: Part 2, Response code is not 200");
+                throw new RuntimeException("Failed: Part 2, Response code is not 200: " + resp);
 
             System.out.println("Response code from Part 2 = 200 OK");
 
-
-        } catch (IOException e) {
-            e.printStackTrace();
-        } catch (URISyntaxException ue) {
-            ue.printStackTrace();
         } finally {
             httpServer.stop(1);
             executorService.shutdown();
@@ -125,7 +128,8 @@
      * Http Server
      */
     public void startHttpServer() throws IOException {
-        httpServer = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        httpServer = HttpServer.create(new InetSocketAddress(loopback, 0), 0);
 
         // create HttpServer context for Part 1.
         HttpContext ctx = httpServer.createContext("/test/", new MyHandler());
--- a/test/jdk/sun/net/www/protocol/http/B6296310.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/B6296310.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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 @@
  * @library ../../httptest/
  * @build HttpCallback TestHttpServer HttpTransaction
  * @run main/othervm B6296310
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6296310
  * @summary  REGRESSION: AppletClassLoader.getResourceAsStream() behaviour is wrong in some cases
  */
 
@@ -45,32 +46,26 @@
    static SimpleHttpTransaction httpTrans;
    static TestHttpServer server;
 
-   public static void main(String[] args)
+   public static void main(String[] args) throws Exception
    {
       ResponseCache.setDefault(new MyCacheHandler());
       startHttpServer();
-
       makeHttpCall();
    }
 
-   public static void startHttpServer() {
-      try {
-         httpTrans = new SimpleHttpTransaction();
-         server = new TestHttpServer(httpTrans, 1, 10, 0);
-      } catch (IOException e) {
-         e.printStackTrace();
-      }
+   public static void startHttpServer() throws IOException {
+     httpTrans = new SimpleHttpTransaction();
+     InetAddress loopback = InetAddress.getLoopbackAddress();
+     server = new TestHttpServer(httpTrans, 1, 10, loopback, 0);
    }
 
-   public static void makeHttpCall() {
+   public static void makeHttpCall() throws IOException {
       try {
          System.out.println("http server listen on: " + server.getLocalPort());
-         URL url = new URL("http" , InetAddress.getLocalHost().getHostAddress(),
+         URL url = new URL("http" , InetAddress.getLoopbackAddress().getHostAddress(),
                             server.getLocalPort(), "/");
-         HttpURLConnection uc = (HttpURLConnection)url.openConnection();
+         HttpURLConnection uc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY);
          System.out.println(uc.getResponseCode());
-      } catch (IOException e) {
-         e.printStackTrace();
       } finally {
          server.terminate();
       }
--- a/test/jdk/sun/net/www/protocol/http/B6299712.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/B6299712.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2019, 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,6 +26,7 @@
  * @bug 6299712 7150552
  * @modules jdk.httpserver
  * @run main/othervm B6299712
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true B6299712
  * @summary  NullPointerException in sun.net.www.protocol.http.HttpURLConnection.followRedirect
  */
 
@@ -54,13 +55,15 @@
 
     public static void main(String[] args) throws Exception {
         ResponseCache.setDefault(new DeployCacheHandler());
+        ProxySelector.setDefault(ProxySelector.of(null)); // no proxy
         startHttpServer();
 
         makeHttpCall();
     }
 
     public static void startHttpServer() throws IOException {
-        server = HttpServer.create(new InetSocketAddress(0), 0);
+        InetAddress address = InetAddress.getLocalHost();
+        server = HttpServer.create(new InetSocketAddress(address, 0), 0);
         server.createContext("/", new DefaultHandler());
         server.createContext("/redirect", new RedirectHandler());
         server.start();
--- a/test/jdk/sun/net/www/protocol/http/NoNTLM.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/NoNTLM.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
  * @modules java.base/sun.net.www
  *          java.base/sun.net.www.protocol.http:open
  * @run main/othervm NoNTLM
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true NoNTLM
  */
 
 import java.io.IOException;
@@ -155,8 +156,8 @@
         System.out.println("====================================");
         System.out.println("Expect client to choose: " + expected);
         System.out.println(reply);
-
-        try (ServerSocket ss = new ServerSocket(0)) {
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        try (ServerSocket ss = new ServerSocket(0, 0, loopback)) {
             Client.start(ss.getLocalPort());
 
             // client ---- GET ---> server
@@ -198,7 +199,8 @@
         System.out.println("Expect client to fail with 401 Unauthorized");
         System.out.println(reply);
 
-        try (ServerSocket ss = new ServerSocket(0)) {
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        try (ServerSocket ss = new ServerSocket(0, 0, loopback)) {
             Client client = new Client(ss.getLocalPort());
             Thread thr = new Thread(client);
             thr.start();
@@ -225,13 +227,14 @@
     }
 
     public static void main(String[] args) throws Exception {
+        boolean ntlmSupported = false;
         try {
             Class<?> ntlmProxyClass = Class.forName("sun.net.www.protocol.http.NTLMAuthenticationProxy", true, NoNTLM.class.getClassLoader());
             Field ntlmSupportedField = ntlmProxyClass.getDeclaredField("supported");
             ntlmSupportedField.setAccessible(true);
             if (ntlmSupportedField.getBoolean(null)) {
-                System.out.println("NTLM is supported. Nothing to do. Exiting.");
-                return;
+                System.out.println("NTLM is supported.");
+                ntlmSupported = true;
             }
         } catch (ClassNotFoundException okay) { }
 
@@ -247,15 +250,26 @@
         test("Basic");
         test("Digest");
         test("Basic", "Digest");
-        test("Basic", "NTLM");
+
+        if (ntlmSupported) {
+            System.out.println("====================================");
+            System.out.println("NTLM is supported: client would select NTLM: skipping `test(\"Basic\", \"NTLM\")`..");
+        } else {
+            test("Basic", "NTLM");
+        }
+
         test("Digest", "NTLM");
         test("Basic", "Digest", "NTLM");
 
-        // test NTLM only, this should fail with "401 Unauthorized"
-        testNTLM();
+        if (ntlmSupported) {
+            System.out.println("====================================");
+            System.out.println("NTLM is supported: client would select NTLM: skipping `testNTLM()`..");
+        } else {
+            // test NTLM only, this should fail with "401 Unauthorized"
+            testNTLM();
+        }
 
         System.out.println();
         System.out.println("TEST PASSED");
     }
 }
-
--- a/test/jdk/sun/net/www/protocol/http/UserAgent.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/UserAgent.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
  * @library /test/lib
  * @modules java.base/sun.net.www
  * @run main/othervm -Dhttp.agent=foo UserAgent
+ * @run main/othervm -Dhttp.agent=foo -Djava.net.preferIPv6Addresses=true UserAgent
  * @summary  HTTP header "User-Agent" format incorrect
  */
 
@@ -87,7 +88,9 @@
 public class UserAgent {
 
     public static void main(String[] args) throws Exception {
-        ServerSocket server = new ServerSocket (0);
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        ServerSocket server = new ServerSocket ();
+        server.bind(new InetSocketAddress(loopback, 0));
         Server s = new Server (server);
         s.start ();
         int port = server.getLocalPort ();
@@ -97,7 +100,7 @@
             .port(port)
             .toURL();
         System.out.println("URL: " + url);
-        URLConnection urlc = url.openConnection ();
+        URLConnection urlc = url.openConnection (Proxy.NO_PROXY);
         urlc.getInputStream ();
         s.join ();
         if (!s.succeeded()) {
--- a/test/jdk/sun/net/www/protocol/http/ZoneId.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/http/ZoneId.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -60,7 +60,7 @@
         out.println("Found an appropriate IPv6 address: " + address);
 
         out.println("Starting http server...");
-        HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
+        HttpServer server = HttpServer.create(new InetSocketAddress(address, 0), 0);
         CompletableFuture<Headers> headers = new CompletableFuture<>();
         server.createContext("/", createCapturingHandler(headers));
         server.start();
--- a/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java	Thu Jun 27 19:14:42 2019 -0400
+++ b/test/jdk/sun/net/www/protocol/https/NewImpl/JavaxHTTPSConnection.java	Fri Jun 28 16:49:32 2019 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2019, 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,7 +25,9 @@
  * @test
  * @bug 4474255
  * @summary Can no longer obtain a com.sun.net.ssl.HttpsURLConnection
+ * @library /test/lib
  * @run main/othervm JavaxHTTPSConnection
+ * @run main/othervm -Djava.net.preferIPv6Addresses=true JavaxHTTPSConnection
  *
  *     SunJSSE does not support dynamic system properties, no way to re-use
  *     system properties in samevm/agentvm mode.
@@ -36,6 +38,7 @@
 import java.net.*;
 import java.security.cert.*;
 import javax.net.ssl.*;
+import jdk.test.lib.net.URIBuilder;
 
 /**
  * See if we can obtain a javax.net.ssl.HttpsURLConnection,
@@ -138,10 +141,13 @@
      */
     void doServerSide() throws Exception {
 
+        InetAddress loopback = InetAddress.getLoopbackAddress();
+        InetSocketAddress serverAddress = new InetSocketAddress(loopback, serverPort);
         SSLServerSocketFactory sslssf =
           (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
         SSLServerSocket sslServerSocket =
-            (SSLServerSocket) sslssf.createServerSocket(serverPort);
+            (SSLServerSocket) sslssf.createServerSocket();
+        sslServerSocket.bind(serverAddress);
         serverPort = sslServerSocket.getLocalPort();
 
         /*
@@ -204,9 +210,14 @@
             }
 
             HttpsURLConnection.setDefaultHostnameVerifier(new NameVerifier());
-            URL url = new URL("https://" + "localhost:" + serverPort +
-                                    "/etc/hosts");
-            URLConnection urlc = url.openConnection();
+            URL url = URIBuilder.newBuilder()
+                .scheme("https")
+                .loopback()
+                .port(serverPort)
+                .path("/etc/hosts")
+                .toURL();
+            System.out.println("Client opening: " + url);
+            URLConnection urlc = url.openConnection(Proxy.NO_PROXY);
 
             if (!(urlc instanceof javax.net.ssl.HttpsURLConnection)) {
                 throw new Exception("URLConnection ! instanceof " +