changeset 10508:e2aa9f6243c2

Merge
author mchung
date Thu, 18 Feb 2016 11:41:21 -0800
parents 7232de4c17c3 8c4603cf805f
children 2805dc5c4cc3
files .hgtags make/lib/Lib-jdk.hotspot.agent.gmk make/share/makefiles/mapfile-vers src/jdk.hotspot.agent/linux/native/libsaproc/libproc_impl.c src/jdk.hotspot.agent/macosx/native/libsaproc/libproc_impl.c src/os/aix/vm/os_aix.cpp src/os/bsd/vm/os_bsd.cpp src/os/solaris/vm/os_solaris.cpp src/os/windows/vm/os_windows.cpp src/share/vm/c1/c1_Runtime1.cpp src/share/vm/ci/ciEnv.cpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/classLoaderData.hpp src/share/vm/classfile/dictionary.cpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/javaClasses.hpp src/share/vm/classfile/javaClasses.inline.hpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/vmSymbols.hpp src/share/vm/interpreter/bytecodeInterpreter.cpp src/share/vm/interpreter/interpreterRuntime.cpp src/share/vm/interpreter/linkResolver.cpp src/share/vm/jvmci/jvmciEnv.cpp src/share/vm/logging/logTag.hpp src/share/vm/memory/universe.cpp src/share/vm/memory/universe.hpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/klass.cpp src/share/vm/oops/klass.hpp src/share/vm/oops/typeArrayKlass.cpp src/share/vm/opto/library_call.cpp src/share/vm/prims/jni.cpp src/share/vm/prims/jvm.cpp src/share/vm/prims/jvm.h src/share/vm/prims/jvmtiEnv.cpp src/share/vm/prims/jvmtiEnvBase.cpp src/share/vm/prims/jvmtiExport.cpp src/share/vm/prims/methodHandles.cpp src/share/vm/prims/whitebox.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/arguments.hpp src/share/vm/runtime/globals.hpp src/share/vm/runtime/os.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/thread.cpp src/share/vm/runtime/vmStructs.cpp test/compiler/escapeAnalysis/TestUnsafePutAddressNullObjMustNotEscape.java test/compiler/jsr292/NonInlinedCall/NonInlinedReinvoker.java test/compiler/jsr292/NonInlinedCall/RedefineTest.java test/compiler/jvmci/code/DataPatchTest.java test/compiler/jvmci/code/SimpleDebugInfoTest.java test/compiler/jvmci/common/CompilerToVMHelper.java test/compiler/jvmci/common/PublicMetaspaceWrapperObject.java test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java test/compiler/jvmci/errors/TestInvalidCompilationResult.java test/compiler/jvmci/errors/TestInvalidDebugInfo.java test/compiler/jvmci/errors/TestInvalidOopMap.java test/compiler/jvmci/events/JvmciNotifyInstallEventTest.java test/compiler/jvmci/events/MetaAccessWrapper.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java test/compiler/stable/StableConfiguration.java test/compiler/stable/TestStableMemoryBarrier.java test/runtime/BadObjectClass/Object.java test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java test/runtime/Unsafe/AllocateInstance.java test/serviceability/dcmd/compiler/CodelistTest.java test/testlibrary/ClassFileInstaller.java test/testlibrary/jdk/test/lib/PerfCounter.java test/testlibrary/jdk/test/lib/PerfCounters.java test/testlibrary_tests/whitebox/vm_flags/IntxTest.java
diffstat 352 files changed, 15963 insertions(+), 2747 deletions(-) [+]
line wrap: on
line diff
--- a/.jcheck/conf	Fri Feb 12 11:07:46 2016 +0100
+++ b/.jcheck/conf	Thu Feb 18 11:41:21 2016 -0800
@@ -1,1 +1,4 @@
 project=jdk9
+comments=lax
+tags=lax
+bugids=dup
--- a/make/bsd/makefiles/mapfile-vers-darwin-debug	Fri Feb 12 11:07:46 2016 +0100
+++ b/make/bsd/makefiles/mapfile-vers-darwin-debug	Thu Feb 18 11:41:21 2016 -0800
@@ -26,7 +26,6 @@
 # Define public interface.
                 _JVM_handle_bsd_signal
 
-		# miscellaneous functions
                 _jio_fprintf
                 _jio_printf
                 _jio_snprintf
--- a/make/share/makefiles/mapfile-vers	Fri Feb 12 11:07:46 2016 +0100
+++ b/make/share/makefiles/mapfile-vers	Thu Feb 18 11:41:21 2016 -0800
@@ -168,3 +168,14 @@
                 JVM_TotalMemory;
                 JVM_UnloadLibrary;
                 JVM_Yield;
+
+                # Module related API's
+                JVM_AddModuleExports;
+                JVM_AddModuleExportsToAll;
+                JVM_AddModuleExportsToAllUnnamed;
+                JVM_AddModulePackage;
+                JVM_AddReadsModule;
+                JVM_CanReadModule;
+                JVM_DefineModule;
+                JVM_IsExportedToModule;
+                JVM_SetBootLoaderUnnamedModule;
--- a/make/solaris/makefiles/mapfile-vers	Fri Feb 12 11:07:46 2016 +0100
+++ b/make/solaris/makefiles/mapfile-vers	Thu Feb 18 11:41:21 2016 -0800
@@ -35,6 +35,7 @@
                 jio_vfprintf;
                 jio_vsnprintf;
 
+
                 # Needed because there is no JVM interface for this.
                 sysThreadAvailableStackWithSlack;
 
--- a/make/test/JtregNative.gmk	Fri Feb 12 11:07:46 2016 +0100
+++ b/make/test/JtregNative.gmk	Thu Feb 18 11:41:21 2016 -0800
@@ -45,6 +45,7 @@
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8025979 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/8033445 \
     $(HOTSPOT_TOPDIR)/test/runtime/jni/ToStringInInterfaceTest \
+    $(HOTSPOT_TOPDIR)/test/runtime/modules/getModuleJNI \
     $(HOTSPOT_TOPDIR)/test/runtime/SameObject \
     $(HOTSPOT_TOPDIR)/test/compiler/floatingpoint/ \
     $(HOTSPOT_TOPDIR)/test/compiler/calls \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/module-info.java	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.hotspot.agent {
+    requires java.datatransfer;
+    requires java.desktop;
+    requires java.rmi;
+    requires java.scripting;
+    requires jdk.jdi;
+
+    exports sun.jvm.hotspot.tools to jdk.jcmd;  // until JDK-8059035 is complete
+    // RMI needs to serialize types in this package
+    exports sun.jvm.hotspot.debugger.remote to java.rmi;
+    provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SACoreAttachingConnector;
+    provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SADebugServerAttachingConnector;
+    provides com.sun.jdi.connect.Connector with sun.jvm.hotspot.jdi.SAPIDAttachingConnector;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/g1/HeapRegionSetCount.java	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+package sun.jvm.hotspot.gc.g1;
+
+import java.util.Iterator;
+import java.util.Observable;
+import java.util.Observer;
+
+import sun.jvm.hotspot.debugger.Address;
+import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.runtime.VMObject;
+import sun.jvm.hotspot.runtime.VMObjectFactory;
+import sun.jvm.hotspot.types.AddressField;
+import sun.jvm.hotspot.types.CIntegerField;
+import sun.jvm.hotspot.types.Type;
+import sun.jvm.hotspot.types.TypeDataBase;
+
+// Mirror class for HeapRegionSetCount. Represents a group of regions.
+
+public class HeapRegionSetCount extends VMObject {
+
+    static private CIntegerField lengthField;
+    static private CIntegerField capacityField;
+
+    static {
+        VM.registerVMInitializedObserver(new Observer() {
+                public void update(Observable o, Object data) {
+                    initialize(VM.getVM().getTypeDataBase());
+                }
+            });
+    }
+
+    static private synchronized void initialize(TypeDataBase db) {
+        Type type = db.lookupType("HeapRegionSetCount");
+
+        lengthField   = type.getCIntegerField("_length");
+        capacityField = type.getCIntegerField("_capacity");
+    }
+
+    public long length() {
+        return lengthField.getValue(addr);
+    }
+
+    public long capacity() {
+        return capacityField.getValue(addr);
+    }
+
+    public HeapRegionSetCount(Address addr) {
+        super(addr);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.vm.ci/share/classes/module-info.java	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+module jdk.vm.ci {
+    uses jdk.vm.ci.hotspot.HotSpotVMEventListener;
+    uses jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
+    uses jdk.vm.ci.runtime.JVMCICompilerFactory;
+
+    provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
+        jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory;
+    provides jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory with
+        jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory;
+}
--- a/src/os/posix/dtrace/hotspot_jni.d	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/os/posix/dtrace/hotspot_jni.d	Thu Feb 18 11:41:21 2016 -0800
@@ -300,6 +300,8 @@
   probe GetLongField__return(uintptr_t);
   probe GetMethodID__entry(void*, void*, const char*, const char*);
   probe GetMethodID__return(uintptr_t);
+  probe GetModule__entry(void*, void*);
+  probe GetModule__return(void*);
   probe GetObjectArrayElement__entry(void*, void*, uintptr_t);
   probe GetObjectArrayElement__return(void*);
   probe GetObjectClass__entry(void*, void*);
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -3094,7 +3094,7 @@
     LIR_Opr klass = new_pointer_register();
     __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), klass_pointer_type), klass, info);
     LIR_Opr id = new_register(T_LONG);
-    ByteSize offset = TRACE_ID_OFFSET;
+    ByteSize offset = TRACE_KLASS_TRACE_ID_OFFSET;
     LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG);
     __ move(trace_id_addr, id);
     __ logical_or(id, LIR_OprFact::longConst(0x01l), id);
--- a/src/share/vm/c1/c1_Runtime1.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -661,7 +661,7 @@
   NOT_PRODUCT(_throw_class_cast_exception_count++;)
   ResourceMark rm(thread);
   char* message = SharedRuntime::generate_class_cast_message(
-    thread, object->klass()->external_name());
+    thread, object->klass());
   SharedRuntime::throw_and_post_jvmti_exception(
     thread, vmSymbols::java_lang_ClassCastException(), message);
 JRT_END
--- a/src/share/vm/ci/ciEnv.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/ci/ciEnv.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -370,9 +370,9 @@
     resolved_klass = ObjArrayKlass::cast(resolved_klass)->bottom_klass();
   }
   if (resolved_klass->is_instance_klass()) {
-    return Reflection::verify_class_access(accessing_klass->get_Klass(),
-                                           resolved_klass,
-                                           true);
+    return (Reflection::verify_class_access(accessing_klass->get_Klass(),
+                                            resolved_klass,
+                                            true) == Reflection::ACCESS_OK);
   }
   return true;
 }
--- a/src/share/vm/classfile/classFileParser.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -28,6 +28,7 @@
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/defaultMethods.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/verificationType.hpp"
@@ -100,8 +101,6 @@
 // Extension method support.
 #define JAVA_8_VERSION                    52
 
-enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
-
 void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
                                                   ConstantPool* cp,
                                                   const int length,
@@ -4355,17 +4354,29 @@
 static void check_super_class_access(const InstanceKlass* this_klass, TRAPS) {
   assert(this_klass != NULL, "invariant");
   const Klass* const super = this_klass->super();
-  if ((super != NULL) &&
-      (!Reflection::verify_class_access(this_klass, super, false))) {
-    ResourceMark rm(THREAD);
-    Exceptions::fthrow(
-      THREAD_AND_LOCATION,
-      vmSymbols::java_lang_IllegalAccessError(),
-      "class %s cannot access its superclass %s",
-      this_klass->external_name(),
-      super->external_name()
-    );
-    return;
+  if (super != NULL) {
+    Reflection::VerifyClassAccessResults vca_result =
+      Reflection::verify_class_access(this_klass, super, false);
+    if (vca_result != Reflection::ACCESS_OK) {
+      ResourceMark rm(THREAD);
+      char* msg =  Reflection::verify_class_access_msg(this_klass, super, vca_result);
+      if (msg == NULL) {
+        ResourceMark rm(THREAD);
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "class %s cannot access its superclass %s",
+          this_klass->external_name(),
+          InstanceKlass::cast(super)->external_name());
+      } else {
+        // Add additional message content.
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "superclass access check failed: %s",
+          msg);
+      }
+    }
   }
 }
 
@@ -4377,16 +4388,26 @@
   for (int i = lng - 1; i >= 0; i--) {
     Klass* const k = local_interfaces->at(i);
     assert (k != NULL && k->is_interface(), "invalid interface");
-    if (!Reflection::verify_class_access(this_klass, k, false)) {
+    Reflection::VerifyClassAccessResults vca_result =
+      Reflection::verify_class_access(this_klass, k, false);
+    if (vca_result != Reflection::ACCESS_OK) {
       ResourceMark rm(THREAD);
-      Exceptions::fthrow(
-        THREAD_AND_LOCATION,
-        vmSymbols::java_lang_IllegalAccessError(),
-        "class %s cannot access its superinterface %s",
-        this_klass->external_name(),
-        k->external_name()
-      );
-      return;
+      char* msg =  Reflection::verify_class_access_msg(this_klass, k, vca_result);
+      if (msg == NULL) {
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "class %s cannot access its superinterface %s",
+          this_klass->external_name(),
+          k->external_name());
+      } else {
+        // Add additional message content.
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "superinterface check failed: %s",
+          msg);
+      }
     }
   }
 }
@@ -4486,12 +4507,14 @@
   const bool is_super      = (flags & JVM_ACC_SUPER)      != 0;
   const bool is_enum       = (flags & JVM_ACC_ENUM)       != 0;
   const bool is_annotation = (flags & JVM_ACC_ANNOTATION) != 0;
+  const bool is_module_info= (flags & JVM_ACC_MODULE)     != 0;
   const bool major_gte_15  = _major_version >= JAVA_1_5_VERSION;
 
   if ((is_abstract && is_final) ||
       (is_interface && !is_abstract) ||
       (is_interface && major_gte_15 && (is_super || is_enum)) ||
-      (!is_interface && major_gte_15 && is_annotation)) {
+      (!is_interface && major_gte_15 && is_annotation) ||
+      is_module_info) {
     ResourceMark rm(THREAD);
     Exceptions::fthrow(
       THREAD_AND_LOCATION,
@@ -4647,65 +4670,9 @@
                                         int length,
                                         TRAPS) const {
   assert(_need_verify, "only called when _need_verify is true");
-  int i = 0;
-  const int count = length >> 2;
-  for (int k=0; k<count; k++) {
-    unsigned char b0 = buffer[i];
-    unsigned char b1 = buffer[i+1];
-    unsigned char b2 = buffer[i+2];
-    unsigned char b3 = buffer[i+3];
-    // For an unsigned char v,
-    // (v | v - 1) is < 128 (highest bit 0) for 0 < v < 128;
-    // (v | v - 1) is >= 128 (highest bit 1) for v == 0 or v >= 128.
-    const unsigned char res = b0 | b0 - 1 |
-                              b1 | b1 - 1 |
-                              b2 | b2 - 1 |
-                              b3 | b3 - 1;
-    if (res >= 128) break;
-    i += 4;
+  if (!UTF8::is_legal_utf8(buffer, length, _major_version <= 47)) {
+    classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
   }
-  for(; i < length; i++) {
-    unsigned short c;
-    // no embedded zeros
-    guarantee_property((buffer[i] != 0), "Illegal UTF8 string in constant pool in class file %s", CHECK);
-    if(buffer[i] < 128) {
-      continue;
-    }
-    if ((i + 5) < length) { // see if it's legal supplementary character
-      if (UTF8::is_supplementary_character(&buffer[i])) {
-        c = UTF8::get_supplementary_character(&buffer[i]);
-        i += 5;
-        continue;
-      }
-    }
-    switch (buffer[i] >> 4) {
-      default: break;
-      case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
-        classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
-      case 0xC: case 0xD:  // 110xxxxx  10xxxxxx
-        c = (buffer[i] & 0x1F) << 6;
-        i++;
-        if ((i < length) && ((buffer[i] & 0xC0) == 0x80)) {
-          c += buffer[i] & 0x3F;
-          if (_major_version <= 47 || c == 0 || c >= 0x80) {
-            // for classes with major > 47, c must a null or a character in its shortest form
-            break;
-          }
-        }
-        classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
-      case 0xE:  // 1110xxxx 10xxxxxx 10xxxxxx
-        c = (buffer[i] & 0xF) << 12;
-        i += 2;
-        if ((i < length) && ((buffer[i-1] & 0xC0) == 0x80) && ((buffer[i] & 0xC0) == 0x80)) {
-          c += ((buffer[i-1] & 0x3F) << 6) + (buffer[i] & 0x3F);
-          if (_major_version <= 47 || c >= 0x800) {
-            // for classes with major > 47, c must be in its shortest form
-            break;
-          }
-        }
-        classfile_parse_error("Illegal UTF8 string in constant pool in class file %s", CHECK);
-    }  // end of switch
-  } // end of for
 }
 
 // Unqualified names may not contain the characters '.', ';', '[', or '/'.
@@ -4713,24 +4680,35 @@
 // or <clinit>.  Note that method names may not be <init> or <clinit> in this
 // method.  Because these names have been checked as special cases before
 // calling this method in verify_legal_method_name.
-static bool verify_unqualified_name(const char* name,
-                                    unsigned int length,
-                                    int type) {
+//
+// This method is also called from the modular system APIs in modules.cpp
+// to verify the validity of module and package names.
+bool ClassFileParser::verify_unqualified_name(const char* name,
+                                              unsigned int length,
+                                              int type) {
   for (const char* p = name; p != name + length;) {
     jchar ch = *p;
     if (ch < 128) {
-      p++;
-      if (ch == '.' || ch == ';' || ch == '[') {
+      if (ch == '.') {
+        // permit '.' in module names unless it's the first char, or
+        // preceding char is also a '.', or last char is a '.'.
+        if ((type != ClassFileParser::LegalModule) ||
+          (p == name) || (*(p-1) == '.') ||
+          (p == name + length - 1)) {
+          return false;
+        }
+      }
+      if (ch == ';' || ch == '[' ) {
         return false;   // do not permit '.', ';', or '['
       }
-      if (type != LegalClass && ch == '/') {
+      if (type != ClassFileParser::LegalClass && ch == '/') {
         return false;   // do not permit '/' unless it's class name
       }
-      if (type == LegalMethod && (ch == '<' || ch == '>')) {
+      if (type == ClassFileParser::LegalMethod && (ch == '<' || ch == '>')) {
         return false;   // do not permit '<' or '>' in method names
       }
-    }
-    else {
+      p++;
+    } else {
       char* tmp_p = UTF8::next(p, &ch);
       p = tmp_p;
     }
@@ -5189,7 +5167,7 @@
   }
 }
 
-InstanceKlass* ClassFileParser::create_instance_klass(TRAPS) {
+InstanceKlass* ClassFileParser::create_instance_klass(bool cf_changed_in_CFLH, TRAPS) {
   if (_klass != NULL) {
     return _klass;
   }
@@ -5197,14 +5175,14 @@
   InstanceKlass* const ik =
     InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);
 
-  fill_instance_klass(ik, CHECK_NULL);
+  fill_instance_klass(ik, cf_changed_in_CFLH, CHECK_NULL);
 
   assert(_klass == ik, "invariant");
 
   return ik;
 }
 
-void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
+void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS) {
   assert(ik != NULL, "invariant");
 
   set_klass_to_deallocate(ik);
@@ -5269,6 +5247,12 @@
     ik->set_host_klass(_host_klass);
   }
 
+  // Set PackageEntry for this_klass
+  oop cl = ik->class_loader();
+  Handle clh = Handle(THREAD, java_lang_ClassLoader::non_reflection_class_loader(cl));
+  ClassLoaderData* cld = ClassLoaderData::class_loader_data_or_null(clh());
+  ik->set_package(ik->name(), cld, CHECK);
+
   const Array<Method*>* const methods = ik->methods();
   assert(methods != NULL, "invariant");
   const int methods_len = methods->length();
@@ -5324,10 +5308,22 @@
     }
   }
 
+  // Obtain this_klass' module entry
+  ModuleEntry* module_entry = ik->module();
+  assert(module_entry != NULL, "module_entry should always be set");
+
+  // Obtain j.l.r.Module
+  oop module_jlrM = (oop)NULL;
+  if (module_entry->jlrM_module() != NULL) {
+    module_jlrM = JNIHandles::resolve(module_entry->jlrM_module());
+  }
+  Handle jlrM_handle(THREAD, module_jlrM);
+
   // Allocate mirror and initialize static fields
   // The create_mirror() call will also call compute_modifiers()
   java_lang_Class::create_mirror(ik,
                                  _loader_data->class_loader(),
+                                 jlrM_handle,
                                  _protection_domain,
                                  CHECK);
 
@@ -5341,6 +5337,15 @@
                                              CHECK);
   }
 
+  // Add read edges to the unnamed modules of the bootstrap and app class loaders.
+  if (cf_changed_in_CFLH && !jlrM_handle.is_null() && module_entry->is_named() &&
+      !module_entry->has_default_read_edges()) {
+    if (!module_entry->set_has_default_read_edges()) {
+      // We won a potential race
+      JvmtiExport::add_default_read_edges(jlrM_handle, THREAD);
+    }
+  }
+
   // Update the loader_data graph.
   record_defined_class_dependencies(ik, CHECK);
 
@@ -5351,9 +5356,19 @@
       ResourceMark rm;
       // print in a single call to reduce interleaving of output
       if (_stream->source() != NULL) {
-        tty->print("[Loaded %s from %s]\n",
-                   ik->external_name(),
-                   _stream->source());
+        static const size_t modules_image_name_len = strlen(MODULES_IMAGE_NAME);
+        size_t stream_len = strlen(_stream->source());
+        // See if _stream->source() ends in "modules"
+        if (module_entry->is_named() && modules_image_name_len < stream_len &&
+          (strncmp(_stream->source() + stream_len - modules_image_name_len,
+                   MODULES_IMAGE_NAME, modules_image_name_len) == 0)) {
+          tty->print_cr("[Loaded %s from jrt:/%s]", ik->external_name(),
+                     module_entry->name()->as_C_string());
+        } else {
+          tty->print("[Loaded %s from %s]\n",
+                     ik->external_name(),
+                     _stream->source());
+        }
       } else if (_loader_data->class_loader() == NULL) {
         const Klass* const caller =
           THREAD->is_Java_thread()
@@ -5395,7 +5410,7 @@
     }
   }
 
-  TRACE_INIT_ID(ik);
+  TRACE_INIT_KLASS_ID(ik);
 
   // If we reach here, all is well.
   // Now remove the InstanceKlass* from the _klass_to_deallocate field
--- a/src/share/vm/classfile/classFileParser.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classFileParser.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -73,6 +73,8 @@
     NOF_PUBLICITY_LEVELS
   };
 
+  enum { LegalClass, LegalField, LegalMethod, LegalModule }; // used to verify unqualified names
+
  private:
   const ClassFileStream* _stream; // Actual input stream
   const Symbol* _requested_name;
@@ -155,7 +157,7 @@
                                   ConstantPool* cp,
                                   TRAPS);
 
-  void fill_instance_klass(InstanceKlass* ik, TRAPS);
+  void fill_instance_klass(InstanceKlass* ik, bool cf_changed_in_CFLH, TRAPS);
   void set_klass(InstanceKlass* instance);
 
   void set_class_synthetic_flag(bool x)        { _synthetic_flag = x; }
@@ -482,7 +484,7 @@
 
   ~ClassFileParser();
 
-  InstanceKlass* create_instance_klass(TRAPS);
+  InstanceKlass* create_instance_klass(bool cf_changed_in_CFLH, TRAPS);
 
   const ClassFileStream* clone_stream() const;
 
@@ -512,6 +514,7 @@
 
   bool is_internal() const { return INTERNAL == _pub_level; }
 
+  static bool verify_unqualified_name(const char* name, unsigned int length, int type);
 };
 
 #endif // SHARE_VM_CLASSFILE_CLASSFILEPARSER_HPP
--- a/src/share/vm/classfile/classLoader.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classLoader.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -29,6 +29,9 @@
 #include "classfile/classLoaderExt.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/jimage.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/klassFactory.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -137,11 +140,14 @@
 ClassPathEntry* ClassLoader::_first_entry         = NULL;
 ClassPathEntry* ClassLoader::_last_entry          = NULL;
 int             ClassLoader::_num_entries         = 0;
-PackageHashtable* ClassLoader::_package_hash_table = NULL;
-
+ClassPathEntry* ClassLoader::_first_append_entry = NULL;
+bool            ClassLoader::_has_jimage = false;
 #if INCLUDE_CDS
+GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
+GrowableArray<char*>* ClassLoader::_ext_modules_array = NULL;
 SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
 #endif
+
 // helper routines
 bool string_starts_with(const char* str, const char* str_to_find) {
   size_t str_len = strlen(str);
@@ -161,7 +167,7 @@
   return (const char*)version_string;
 }
 
-bool string_ends_with(const char* str, const char* str_to_find) {
+bool ClassLoader::string_ends_with(const char* str, const char* str_to_find) {
   size_t str_len = strlen(str);
   size_t str_to_find_len = strlen(str_to_find);
   if (str_to_find_len > str_len) {
@@ -355,15 +361,49 @@
   if (location == 0) {
     char package[JIMAGE_MAX_PATH];
     name_to_package(name, package, JIMAGE_MAX_PATH);
+
+#if INCLUDE_CDS
+    if (package[0] == '\0' && DumpSharedSpaces) {
+      return NULL;
+    }
+#endif
     if (package[0] != '\0') {
-        const char* module = (*JImagePackageToModule)(_jimage, package);
-        if (module == NULL) {
-            module = "java.base";
+      if (!Universe::is_module_initialized()) {
+        location = (*JImageFindResource)(_jimage, "java.base", get_jimage_version_string(), name, &size);
+#if INCLUDE_CDS
+        // CDS uses the boot class loader to load classes whose packages are in
+        // modules defined for other class loaders.  So, for now, get their module
+        // names from the "modules" jimage file.
+        if (DumpSharedSpaces && location == 0) {
+          const char* module_name = (*JImagePackageToModule)(_jimage, package);
+          if (module_name != NULL) {
+            location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
+          }
         }
-        location = (*JImageFindResource)(_jimage, module, get_jimage_version_string(), name, &size);
+#endif
+
+      } else {
+        // Get boot class loader's package entry table
+        PackageEntryTable* pkgEntryTable =
+          ClassLoaderData::the_null_class_loader_data()->packages();
+        // Get package's package entry
+        TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package, CHECK_NULL);
+        PackageEntry* package_entry = pkgEntryTable->lookup_only(pkg_symbol);
+
+        if (package_entry != NULL) {
+          ResourceMark rm;
+          // Get the module name
+          ModuleEntry* module = package_entry->module();
+          assert(module != NULL, "Boot classLoader package missing module");
+          assert(module->is_named(), "Boot classLoader package is in unnamed module");
+          const char* module_name = module->name()->as_C_string();
+          if (module_name != NULL) {
+            location = (*JImageFindResource)(_jimage, module_name, get_jimage_version_string(), name, &size);
+          }
+        }
+      }
     }
   }
-
   if (location != 0) {
     if (UsePerfData) {
       ClassLoader::perf_sys_classfile_bytes_read()->inc(size);
@@ -408,11 +448,11 @@
     }
   }
 }
+#endif
 
 bool ClassPathImageEntry::is_jrt() {
-  return string_ends_with(name(), BOOT_IMAGE_NAME);
+  return ClassLoader::is_jrt(name());
 }
-#endif
 
 #if INCLUDE_CDS
 void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
@@ -474,14 +514,15 @@
     // Don't print sys_class_path - this is the bootcp of this current VM process, not necessarily
     // the same as the bootcp of the shared archive.
   } else {
-    trace_class_path(tty, "[Bootstrap loader class path=", sys_class_path);
+    trace_class_path(tty, "[Bootstrap loader class path=",
+                     Arguments::get_property("jdk.boot.class.path.append"));
   }
 #if INCLUDE_CDS
   if (DumpSharedSpaces) {
     _shared_paths_misc_info->add_boot_classpath(sys_class_path);
   }
 #endif
-  setup_search_path(sys_class_path);
+  setup_search_path(sys_class_path, true);
 }
 
 #if INCLUDE_CDS
@@ -501,10 +542,11 @@
 }
 #endif
 
-void ClassLoader::setup_search_path(const char *class_path) {
+void ClassLoader::setup_search_path(const char *class_path, bool bootstrap_search) {
   int offset = 0;
   int len = (int)strlen(class_path);
   int end = 0;
+  bool mark_append_entry = false;
 
   // Iterate over class path entries
   for (int start = 0; start < len; start = end) {
@@ -513,10 +555,23 @@
     }
     EXCEPTION_MARK;
     ResourceMark rm(THREAD);
+    mark_append_entry = (mark_append_entry ||
+      (bootstrap_search && (start == Arguments::bootclassloader_append_index())));
     char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
     strncpy(path, &class_path[start], end - start);
     path[end - start] = '\0';
-    update_class_path_entry_list(path, false);
+    update_class_path_entry_list(path, false, mark_append_entry, false);
+
+    // Check on the state of the boot loader's append path
+    if (mark_append_entry && (_first_append_entry == NULL)) {
+      // Failure to mark the first append entry, most likely
+      // due to a non-existent path. Record the next entry
+      // as the first boot loader append entry.
+      mark_append_entry = true;
+    } else {
+      mark_append_entry = false;
+    }
+
 #if INCLUDE_CDS
     if (DumpSharedSpaces) {
       check_shared_classpath(path);
@@ -620,6 +675,18 @@
   return NULL;
 }
 
+// The boot class loader must adhere to specfic visibility rules.
+// Prior to loading a class in a named package, the package is checked
+// to see if it is in a module defined to the boot loader. If the
+// package is not in a module defined to the boot loader, the class
+// must be loaded only in the boot loader's append path, which
+// consists of [-Xbootclasspath/a]; [jvmti appended entries]
+void ClassLoader::set_first_append_entry(ClassPathEntry *new_entry) {
+  if (_first_append_entry == NULL) {
+    _first_append_entry = new_entry;
+  }
+}
+
 // returns true if entry already on class path
 bool ClassLoader::contains_entry(ClassPathEntry *entry) {
   ClassPathEntry* e = _first_entry;
@@ -645,9 +712,31 @@
   _num_entries ++;
 }
 
+void ClassLoader::prepend_to_list(ClassPathEntry *new_entry) {
+  if (new_entry != NULL) {
+    if (_last_entry == NULL) {
+      _first_entry = _last_entry = new_entry;
+    } else {
+      new_entry->set_next(_first_entry);
+      _first_entry = new_entry;
+    }
+  }
+  _num_entries ++;
+}
+
+void ClassLoader::add_to_list(const char *apath) {
+  update_class_path_entry_list((char*)apath, false, false, false);
+}
+
+void ClassLoader::prepend_to_list(const char *apath) {
+  update_class_path_entry_list((char*)apath, false, false, true);
+}
+
 // Returns true IFF the file/dir exists and the entry was successfully created.
 bool ClassLoader::update_class_path_entry_list(const char *path,
                                                bool check_for_duplicates,
+                                               bool mark_append_entry,
+                                               bool prepend_entry,
                                                bool throw_exception) {
   struct stat st;
   if (os::stat(path, &st) == 0) {
@@ -658,12 +747,20 @@
     if (new_entry == NULL) {
       return false;
     }
-    // The kernel VM adds dynamically to the end of the classloader path and
-    // doesn't reorder the bootclasspath which would break java.lang.Package
-    // (see PackageInfo).
+
+    // Ensure that the first boot loader append entry will always be set correctly.
+    assert((!mark_append_entry ||
+            (mark_append_entry && (!check_for_duplicates || !contains_entry(new_entry)))),
+           "failed to mark boot loader's first append boundary");
+
+    // Do not reorder the bootclasspath which would break get_system_package().
     // Add new entry to linked list
+
     if (!check_for_duplicates || !contains_entry(new_entry)) {
-      ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry);
+      ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry, prepend_entry);
+      if (mark_append_entry) {
+        set_first_append_entry(new_entry);
+      }
     }
     return true;
   } else {
@@ -764,246 +861,206 @@
   return (*Crc32)(crc, (const jbyte*)buf, len);
 }
 
-// PackageInfo data exists in order to support the java.lang.Package
-// class.  A Package object provides information about a java package
-// (version, vendor, etc.) which originates in the manifest of the jar
-// file supplying the package.  For application classes, the ClassLoader
-// object takes care of this.
-
-// For system (boot) classes, the Java code in the Package class needs
-// to be able to identify which source jar file contained the boot
-// class, so that it can extract the manifest from it.  This table
-// identifies java packages with jar files in the boot classpath.
-
-// Because the boot classpath cannot change, the classpath index is
-// sufficient to identify the source jar file or directory.  (Since
-// directories have no manifests, the directory name is not required,
-// but is available.)
-
-// When using sharing -- the pathnames of entries in the boot classpath
-// may not be the same at runtime as they were when the archive was
-// created (NFS, Samba, etc.).  The actual files and directories named
-// in the classpath must be the same files, in the same order, even
-// though the exact name is not the same.
-
-class PackageInfo: public BasicHashtableEntry<mtClass> {
-public:
-  const char* _pkgname;       // Package name
-  int _classpath_index;       // Index of directory or JAR file loaded from
-
-  PackageInfo* next() {
-    return (PackageInfo*)BasicHashtableEntry<mtClass>::next();
+#if INCLUDE_CDS
+void ClassLoader::initialize_module_loader_map(JImageFile* jimage) {
+  jlong size;
+  JImageLocationRef location = (*JImageFindResource)(jimage, "java.base", get_jimage_version_string(), MODULE_LOADER_MAP, &size);
+  if (location == 0) {
+    vm_exit_during_initialization(
+      "Cannot find ModuleLoaderMap location from modules jimage.", NULL);
   }
-
-  const char* pkgname()           { return _pkgname; }
-  void set_pkgname(char* pkgname) { _pkgname = pkgname; }
-
-  const char* filename() {
-    return ClassLoader::classpath_entry(_classpath_index)->name();
+  char* buffer = NEW_RESOURCE_ARRAY(char, size);
+  jlong read = (*JImageGetResource)(jimage, location, buffer, size);
+  if (read != size) {
+    vm_exit_during_initialization(
+      "Cannot find ModuleLoaderMap resource from modules jimage.", NULL);
   }
-
-  void set_index(int index) {
-    _classpath_index = index;
-  }
-};
-
-
-class PackageHashtable : public BasicHashtable<mtClass> {
-private:
-  inline unsigned int compute_hash(const char *s, int n) {
-    unsigned int val = 0;
-    while (--n >= 0) {
-      val = *s++ + 31 * val;
-    }
-    return val;
-  }
-
-  PackageInfo* bucket(int index) {
-    return (PackageInfo*)BasicHashtable<mtClass>::bucket(index);
-  }
-
-  PackageInfo* get_entry(int index, unsigned int hash,
-                         const char* pkgname, size_t n) {
-    for (PackageInfo* pp = bucket(index); pp != NULL; pp = pp->next()) {
-      if (pp->hash() == hash &&
-          strncmp(pkgname, pp->pkgname(), n) == 0 &&
-          pp->pkgname()[n] == '\0') {
-        return pp;
+  char* char_buf = (char*)buffer;
+  int buflen = (int)strlen(char_buf);
+  char* begin_ptr = char_buf;
+  char* end_ptr = strchr(begin_ptr, '\n');
+  bool process_boot_modules = false;
+  _boot_modules_array = new (ResourceObj::C_HEAP, mtInternal)
+    GrowableArray<char*>(INITIAL_BOOT_MODULES_ARRAY_SIZE, true);
+  _ext_modules_array = new (ResourceObj::C_HEAP, mtInternal)
+    GrowableArray<char*>(INITIAL_EXT_MODULES_ARRAY_SIZE, true);
+  while (end_ptr != NULL && (end_ptr - char_buf) < buflen) {
+    // Allocate a buffer from the C heap to be appended to the _boot_modules_array
+    // or the _ext_modules_array.
+    char* temp_name = NEW_C_HEAP_ARRAY(char, (size_t)(end_ptr - begin_ptr + 1), mtInternal);
+    strncpy(temp_name, begin_ptr, end_ptr - begin_ptr);
+    temp_name[end_ptr - begin_ptr] = '\0';
+    if (strncmp(temp_name, "BOOT", 4) == 0) {
+      process_boot_modules = true;
+      FREE_C_HEAP_ARRAY(char, temp_name);
+    } else if (strncmp(temp_name, "EXT", 3) == 0) {
+      process_boot_modules = false;
+      FREE_C_HEAP_ARRAY(char, temp_name);
+    } else {
+      // module name
+      if (process_boot_modules) {
+        _boot_modules_array->append(temp_name);
+      } else {
+        _ext_modules_array->append(temp_name);
       }
     }
-    return NULL;
+    begin_ptr = ++end_ptr;
+    end_ptr = strchr(begin_ptr, '\n');
   }
-
-public:
-  PackageHashtable(int table_size)
-    : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo)) {}
-
-  PackageHashtable(int table_size, HashtableBucket<mtClass>* t, int number_of_entries)
-    : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo), t, number_of_entries) {}
-
-  PackageInfo* get_entry(const char* pkgname, int n) {
-    unsigned int hash = compute_hash(pkgname, n);
-    return get_entry(hash_to_index(hash), hash, pkgname, n);
-  }
-
-  PackageInfo* new_entry(char* pkgname, int n) {
-    unsigned int hash = compute_hash(pkgname, n);
-    PackageInfo* pp;
-    pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
-    pp->set_pkgname(pkgname);
-    return pp;
-  }
-
-  void add_entry(PackageInfo* pp) {
-    int index = hash_to_index(pp->hash());
-    BasicHashtable<mtClass>::add_entry(index, pp);
-  }
-
-  void copy_pkgnames(const char** packages) {
-    int n = 0;
-    for (int i = 0; i < table_size(); ++i) {
-      for (PackageInfo* pp = bucket(i); pp != NULL; pp = pp->next()) {
-        packages[n++] = pp->pkgname();
-      }
-    }
-    assert(n == number_of_entries(), "just checking");
-  }
-
-  CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
-};
-
-#if INCLUDE_CDS
-void PackageHashtable::copy_table(char** top, char* end,
-                                  PackageHashtable* table) {
-  // Copy (relocate) the table to the shared space.
-  BasicHashtable<mtClass>::copy_table(top, end);
-
-  // Calculate the space needed for the package name strings.
-  int i;
-  intptr_t* tableSize = (intptr_t*)(*top);
-  *top += sizeof(intptr_t);  // For table size
-  char* tableStart = *top;
-
-  for (i = 0; i < table_size(); ++i) {
-    for (PackageInfo* pp = table->bucket(i);
-                      pp != NULL;
-                      pp = pp->next()) {
-      int n1 = (int)(strlen(pp->pkgname()) + 1);
-      if (*top + n1 >= end) {
-        report_out_of_shared_space(SharedMiscData);
-      }
-      pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1));
-      *top += n1;
-    }
-  }
-  *top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord));
-  if (*top >= end) {
-    report_out_of_shared_space(SharedMiscData);
-  }
-
-  // Write table size
-  intptr_t len = *top - (char*)tableStart;
-  *tableSize = len;
-}
-
-
-void ClassLoader::copy_package_info_buckets(char** top, char* end) {
-  _package_hash_table->copy_buckets(top, end);
-}
-
-void ClassLoader::copy_package_info_table(char** top, char* end) {
-  _package_hash_table->copy_table(top, end, _package_hash_table);
+  FREE_RESOURCE_ARRAY(u1, buffer, size);
 }
 #endif
 
-PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
-  const char *cp = strrchr(pkgname, '/');
+// Function add_package extracts the package from the fully qualified class name
+// and checks if the package is in the boot loader's package entry table.  If so,
+// then it sets the classpath_index in the package entry record.
+//
+// The classpath_index field is used to find the entry on the boot loader class
+// path for packages with classes loaded by the boot loader from -Xbootclasspath/a
+// in an unnamed module.  It is also used to indicate (for all packages whose
+// classes are loaded by the boot loader) that at least one of the package's
+// classes has been loaded.
+bool ClassLoader::add_package(const char *fullq_class_name, s2 classpath_index, TRAPS) {
+  assert(fullq_class_name != NULL, "just checking");
+
+  // Get package name from fully qualified class name.
+  const char *cp = strrchr(fullq_class_name, '/');
   if (cp != NULL) {
-    // Package prefix found
-    int n = cp - pkgname + 1;
-    return _package_hash_table->get_entry(pkgname, n);
+    int len = cp - fullq_class_name;
+    PackageEntryTable* pkg_entry_tbl =
+      ClassLoaderData::the_null_class_loader_data()->packages();
+    TempNewSymbol pkg_symbol =
+      SymbolTable::new_symbol(fullq_class_name, len, CHECK_false);
+    PackageEntry* pkg_entry = pkg_entry_tbl->lookup_only(pkg_symbol);
+    if (pkg_entry != NULL) {
+      assert(classpath_index != -1, "Unexpected classpath_index");
+      pkg_entry->set_classpath_index(classpath_index);
+    } else {
+      return false;
+    }
+  }
+  return true;
+}
+
+oop ClassLoader::get_system_package(const char* name, TRAPS) {
+  // Look up the name in the boot loader's package entry table.
+  if (name != NULL) {
+    TempNewSymbol package_sym = SymbolTable::new_symbol(name, (int)strlen(name), CHECK_NULL);
+    // Look for the package entry in the boot loader's package entry table.
+    PackageEntry* package =
+      ClassLoaderData::the_null_class_loader_data()->packages()->lookup_only(package_sym);
+
+    // Return NULL if package does not exist or if no classes in that package
+    // have been loaded.
+    if (package != NULL && package->has_loaded_class()) {
+      ModuleEntry* module = package->module();
+      if (module->location() != NULL) {
+        ResourceMark rm(THREAD);
+        Handle ml = java_lang_String::create_from_str(
+          module->location()->as_C_string(), THREAD);
+        return ml();
+      }
+      // Return entry on boot loader class path.
+      Handle cph = java_lang_String::create_from_str(
+        ClassLoader::classpath_entry(package->classpath_index())->name(), THREAD);
+      return cph();
+    }
   }
   return NULL;
 }
 
+objArrayOop ClassLoader::get_system_packages(TRAPS) {
+  ResourceMark rm(THREAD);
+  // List of pointers to PackageEntrys that have loaded classes.
+  GrowableArray<PackageEntry*>* loaded_class_pkgs = new GrowableArray<PackageEntry*>(50);
+  {
+    MutexLocker ml(Module_lock, THREAD);
 
-bool ClassLoader::add_package(const char *pkgname, int classpath_index, TRAPS) {
-  assert(pkgname != NULL, "just checking");
-  // Bootstrap loader no longer holds system loader lock obj serializing
-  // load_instance_class and thereby add_package
-  {
-    MutexLocker ml(PackageTable_lock, THREAD);
-    // First check for previously loaded entry
-    PackageInfo* pp = lookup_package(pkgname);
-    if (pp != NULL) {
-      // Existing entry found, check source of package
-      pp->set_index(classpath_index);
-      return true;
+    PackageEntryTable* pe_table =
+      ClassLoaderData::the_null_class_loader_data()->packages();
+
+    // Collect the packages that have at least one loaded class.
+    for (int x = 0; x < pe_table->table_size(); x++) {
+      for (PackageEntry* package_entry = pe_table->bucket(x);
+           package_entry != NULL;
+           package_entry = package_entry->next()) {
+        if (package_entry->has_loaded_class()) {
+          loaded_class_pkgs->append(package_entry);
+        }
+      }
     }
+  }
 
-    const char *cp = strrchr(pkgname, '/');
-    if (cp != NULL) {
-      // Package prefix found
-      int n = cp - pkgname + 1;
 
-      char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1, mtClass);
-      if (new_pkgname == NULL) {
-        return false;
-      }
-
-      memcpy(new_pkgname, pkgname, n);
-      new_pkgname[n] = '\0';
-      pp = _package_hash_table->new_entry(new_pkgname, n);
-      pp->set_index(classpath_index);
-
-      // Insert into hash table
-      _package_hash_table->add_entry(pp);
-    }
-    return true;
+  // Allocate objArray and fill with java.lang.String
+  objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
+                                           loaded_class_pkgs->length(), CHECK_NULL);
+  objArrayHandle result(THREAD, r);
+  for (int x = 0; x < loaded_class_pkgs->length(); x++) {
+    PackageEntry* package_entry = loaded_class_pkgs->at(x);
+    Handle str = java_lang_String::create_from_symbol(package_entry->name(), CHECK_NULL);
+    result->obj_at_put(x, str());
   }
+  return result();
 }
 
+#if INCLUDE_CDS
+jshort ClassLoader::module_to_classloader(const char* module_name) {
 
-oop ClassLoader::get_system_package(const char* name, TRAPS) {
-  PackageInfo* pp;
-  {
-    MutexLocker ml(PackageTable_lock, THREAD);
-    pp = lookup_package(name);
+  assert(_boot_modules_array != NULL, "_boot_modules_array is NULL");
+  assert(_ext_modules_array != NULL, "_ext_modules_array is NULL");
+
+  int array_size = _boot_modules_array->length();
+  for (int i = 0; i < array_size; i++) {
+    if (strcmp(module_name, _boot_modules_array->at(i)) == 0) {
+      return BOOT;
+    }
   }
-  if (pp == NULL) {
-    return NULL;
-  } else {
-    Handle p = java_lang_String::create_from_str(pp->filename(), THREAD);
-    return p();
+
+  array_size = _ext_modules_array->length();
+  for (int i = 0; i < array_size; i++) {
+    if (strcmp(module_name, _ext_modules_array->at(i)) == 0) {
+      return EXT;
+    }
   }
+
+  return APP;
+}
+#endif
+
+jshort ClassLoader::classloader_type(Symbol* class_name, ClassPathEntry* e,
+                                     int classpath_index, TRAPS) {
+#if INCLUDE_CDS
+  // obtain the classloader type based on the class name.
+  // First obtain the package name based on the class name. Then obtain
+  // the classloader type based on the package name from the jimage using
+  // a jimage API. If the classloader type cannot be found from the
+  // jimage, it is determined by the class path entry.
+  jshort loader_type = ClassLoader::APP;
+  if (e->is_jrt()) {
+    int length;
+    const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+    TempNewSymbol pkg_name = NULL;
+    if (pkg_string != NULL) {
+      ResourceMark rm;
+      pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, THREAD);
+      const char* pkg_name_C_string = (const char*)(pkg_name->as_C_string());
+      ClassPathImageEntry* cpie = (ClassPathImageEntry*)e;
+      JImageFile* jimage = cpie->jimage();
+      char* module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name_C_string);
+      if (module_name != NULL) {
+        loader_type = ClassLoader::module_to_classloader(module_name);
+      }
+    }
+  } else if (ClassLoaderExt::is_boot_classpath(classpath_index)) {
+    loader_type = ClassLoader::BOOT;
+  }
+  return loader_type;
+#endif
+  return ClassLoader::BOOT; // the classloader type is ignored in non-CDS cases
 }
 
 
-objArrayOop ClassLoader::get_system_packages(TRAPS) {
-  ResourceMark rm(THREAD);
-  int nof_entries;
-  const char** packages;
-  {
-    MutexLocker ml(PackageTable_lock, THREAD);
-    // Allocate resource char* array containing package names
-    nof_entries = _package_hash_table->number_of_entries();
-    if ((packages = NEW_RESOURCE_ARRAY(const char*, nof_entries)) == NULL) {
-      return NULL;
-    }
-    _package_hash_table->copy_pkgnames(packages);
-  }
-  // Allocate objArray and fill with java.lang.String
-  objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
-                                           nof_entries, CHECK_0);
-  objArrayHandle result(THREAD, r);
-  for (int i = 0; i < nof_entries; i++) {
-    Handle str = java_lang_String::create_from_str(packages[i], CHECK_0);
-    result->obj_at_put(i, str());
-  }
-
-  return result();
-}
-
 // caller needs ResourceMark
 const char* ClassLoader::file_name_for_class_name(const char* class_name,
                                                   int class_name_len) {
@@ -1022,7 +1079,7 @@
   return file_name;
 }
 
-instanceKlassHandle ClassLoader::load_class(Symbol* name, TRAPS) {
+instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
 
   assert(name != NULL, "invariant");
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
@@ -1041,24 +1098,54 @@
 
   ClassLoaderExt::Context context(class_name, file_name, THREAD);
 
-  // Lookup stream
+  // Lookup stream for parsing .class file
   ClassFileStream* stream = NULL;
-  int classpath_index = 0;
-  ClassPathEntry* e = _first_entry;
+  s2 classpath_index = 0;
+
+  // If DumpSharedSpaces is true, boot loader visibility boundaries are set
+  // to be _first_entry to the end (all path entries).
+  //
+  // If search_append_only is true, boot loader visibility boundaries are
+  // set to be _fist_append_entry to the end. This includes:
+  //   [-Xbootclasspath/a]; [jvmti appended entries]
+  //
+  // If both DumpSharedSpaces and search_append_only are false, boot loader
+  // visibility boundaries are set to be _first_entry to the entry before
+  // the _first_append_entry.  This would include:
+  //   [-Xpatch:<dirs>];  [exploded build | modules]
+  //
+  // DumpSharedSpaces and search_append_only are mutually exclusive and cannot
+  // be true at the same time.
+  ClassPathEntry* e = (search_append_only ? _first_append_entry : _first_entry);
+  ClassPathEntry* last_e =
+      (search_append_only || DumpSharedSpaces ? NULL : _first_append_entry);
+
   {
-    PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
-      ((JavaThread*)THREAD)->get_thread_stat()->perf_timers_addr(),
-      PerfClassTraceTime::CLASS_LOAD);
+    if (search_append_only) {
+      // For the boot loader append path search, must calculate
+      // the starting classpath_index prior to attempting to
+      // load the classfile.
+      ClassPathEntry *tmp_e = _first_entry;
+      while ((tmp_e != NULL) && (tmp_e != _first_append_entry)) {
+        tmp_e = tmp_e->next();
+        ++classpath_index;
+      }
+    }
 
-    for (; e != NULL; e = e->next(), ++classpath_index) {
+    // Attempt to load the classfile from either:
+    //   - [-Xpatch:dir]; exploded build | modules
+    //     or
+    //   - [-Xbootclasspath/a]; [jvmti appended entries]
+    while ((e != NULL) && (e != last_e)) {
       stream = e->open_stream(file_name, CHECK_NULL);
-      if (NULL == stream) {
-        continue;
-      }
       if (!context.check(stream, classpath_index)) {
         return NULL;
       }
-      break;
+      if (NULL != stream) {
+        break;
+      }
+      e = e->next();
+      ++classpath_index;
     }
   }
 
@@ -1089,32 +1176,16 @@
     return NULL;
   }
 
-  return context.record_result(classpath_index, e, result, THREAD);
+  jshort loader_type = classloader_type(name, e, classpath_index, CHECK_NULL);
+  return context.record_result(classpath_index, loader_type, e, result, THREAD);
 }
 
-void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int length,
-                                            int number_of_entries) {
-  assert(_package_hash_table == NULL, "One package info table allowed.");
-  assert(length == package_hash_table_size * sizeof(HashtableBucket<mtClass>),
-         "bad shared package info size.");
-  _package_hash_table = new PackageHashtable(package_hash_table_size, t,
-                                             number_of_entries);
-}
-
-
-void ClassLoader::create_package_info_table() {
-    assert(_package_hash_table == NULL, "shouldn't have one yet");
-    _package_hash_table = new PackageHashtable(package_hash_table_size);
-}
-
-
 // Initialize the class loader's access to methods in libzip.  Parse and
 // process the boot classpath into a list ClassPathEntry objects.  Once
 // this list has been created, it must not change order (see class PackageInfo)
 // it can be appended to and is by jvmti and the kernel vm.
 
 void ClassLoader::initialize() {
-  assert(_package_hash_table == NULL, "should have been initialized by now.");
   EXCEPTION_MARK;
 
   if (UsePerfData) {
@@ -1262,12 +1333,48 @@
   return true;
 }
 
-#ifndef PRODUCT
+void ClassLoader::create_javabase() {
+  Thread* THREAD = Thread::current();
 
-void ClassLoader::verify() {
-  _package_hash_table->verify();
+  // Create java.base's module entry for the boot
+  // class loader prior to loading j.l.Ojbect.
+  ClassLoaderData* null_cld = ClassLoaderData::the_null_class_loader_data();
+
+  // Get module entry table
+  ModuleEntryTable* null_cld_modules = null_cld->modules();
+  if (null_cld_modules == NULL) {
+    vm_exit_during_initialization("No ModuleEntryTable for the boot class loader");
+  }
+
+  {
+    MutexLocker ml(Module_lock, THREAD);
+    ModuleEntry* jb_module = null_cld_modules->locked_create_entry_or_null(Handle(NULL), vmSymbols::java_base(), NULL, NULL, null_cld);
+    if (jb_module == NULL) {
+      vm_exit_during_initialization("Unable to create ModuleEntry for java.base");
+    }
+    ModuleEntryTable::set_javabase_module(jb_module);
+  }
+
+  // When looking for the jimage file, only
+  // search the boot loader's module path which
+  // can consist of [-Xpatch]; exploded build | modules
+  // Do not search the boot loader's append path.
+  ClassPathEntry* e = _first_entry;
+  ClassPathEntry* last_e = _first_append_entry;
+  while ((e != NULL) && (e != last_e)) {
+    JImageFile *jimage = e->jimage();
+    if (jimage != NULL && e->is_jrt()) {
+      set_has_jimage(true);
+#if INCLUDE_CDS
+      ClassLoader::initialize_module_loader_map(jimage);
+#endif
+      return;
+    }
+    e = e->next();
+  }
 }
 
+#ifndef PRODUCT
 
 // CompileTheWorld
 //
@@ -1329,10 +1436,6 @@
   tty->cr();
 }
 
-bool ClassPathDirEntry::is_jrt() {
-  return false;
-}
-
 void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
   real_jzfile* zip = (real_jzfile*) _zip;
   tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
@@ -1354,10 +1457,6 @@
   }
 }
 
-bool ClassPathZipEntry::is_jrt() {
-  return false;
-}
-
 void ClassLoader::compile_the_world() {
   EXCEPTION_MARK;
   HandleMark hm(THREAD);
@@ -1370,7 +1469,7 @@
   ClassPathEntry* e = _first_entry;
   jlong start = os::javaTimeMillis();
   while (e != NULL) {
-    // We stop at bootmodules.jimage, unless it is the first bootstrap path entry
+    // We stop at "modules" jimage, unless it is the first bootstrap path entry
     if (e->is_jrt() && e != _first_entry) break;
     e->compile_the_world(system_class_loader, CATCH);
     e = e->next();
--- a/src/share/vm/classfile/classLoader.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classLoader.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -33,8 +33,17 @@
 // The VM class loader.
 #include <sys/stat.h>
 
-// Name of boot module image
-#define  BOOT_IMAGE_NAME "bootmodules.jimage"
+// Name of boot "modules" image
+#define  MODULES_IMAGE_NAME "modules"
+
+// Name of the resource containing mapping from module names to defining class loader type
+#define MODULE_LOADER_MAP "jdk/internal/module/ModuleLoaderMap.dat"
+
+// Initial sizes of the following arrays are based on the generated ModuleLoaderMap.dat
+#define INITIAL_BOOT_MODULES_ARRAY_SIZE 30
+#define INITIAL_EXT_MODULES_ARRAY_SIZE  15
+
+// Class path entry (directory or zip file)
 
 class JImageFile;
 class ClassFileStream;
@@ -49,6 +58,7 @@
     // may have unlocked readers, so write atomically.
     OrderAccess::release_store_ptr(&_next, next);
   }
+  virtual bool is_jrt() = 0;
   virtual bool is_jar_file() const = 0;
   virtual const char* name() const = 0;
   virtual JImageFile* jimage() const = 0;
@@ -59,13 +69,13 @@
   virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
   // Debugging
   NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
-    NOT_PRODUCT(virtual bool is_jrt() = 0;)
 };
 
 class ClassPathDirEntry: public ClassPathEntry {
  private:
   const char* _dir;           // Name of directory
  public:
+  bool is_jrt()            { return false; }
   bool is_jar_file() const { return false;  }
   const char* name() const { return _dir; }
   JImageFile* jimage() const { return NULL; }
@@ -73,7 +83,6 @@
   ClassFileStream* open_stream(const char* name, TRAPS);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_jrt();)
 };
 
 
@@ -96,6 +105,7 @@
   jzfile* _zip;              // The zip archive
   const char*   _zip_name;   // Name of zip archive
  public:
+  bool is_jrt()            { return false; }
   bool is_jar_file() const { return true;  }
   const char* name() const { return _zip_name; }
   JImageFile* jimage() const { return NULL; }
@@ -106,7 +116,6 @@
   void contents_do(void f(const char* name, void* context), void* context);
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_jrt();)
 };
 
 
@@ -116,29 +125,28 @@
   JImageFile* _jimage;
   const char* _name;
 public:
+  bool is_jrt();
   bool is_jar_file() const { return false; }
   bool is_open() const { return _jimage != NULL; }
   const char* name() const { return _name == NULL ? "" : _name; }
   JImageFile* jimage() const { return _jimage; }
   ClassPathImageEntry(JImageFile* jimage, const char* name);
   ~ClassPathImageEntry();
-  static void name_to_package(const char* name, char* buffer, int length);
+  void name_to_package(const char* name, char* package, int length);
   ClassFileStream* open_stream(const char* name, TRAPS);
 
   // Debugging
   NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
-  NOT_PRODUCT(bool is_jrt();)
 };
 
-class PackageHashtable;
-class PackageInfo;
 class SharedPathsMiscInfo;
-template <MEMFLAGS F> class HashtableBucket;
 
 class ClassLoader: AllStatic {
  public:
-  enum SomeConstants {
-    package_hash_table_size = 31  // Number of buckets
+  enum ClassLoaderType {
+    BOOT = 1,
+    EXT  = 2,
+    APP  = 3
   };
  protected:
 
@@ -177,41 +185,60 @@
   static PerfCounter* _isUnsyncloadClass;
   static PerfCounter* _load_instance_class_failCounter;
 
-  // First entry in linked list of ClassPathEntry instances
+  // First entry in linked list of ClassPathEntry instances.
+  // This consists of entries made up by:
+  //   - boot loader modules
+  //     [-Xpatch]; exploded build | modules;
+  //   - boot loader append path
+  //     [-Xbootclasspath/a]; [jvmti appended entries]
   static ClassPathEntry* _first_entry;
   // Last entry in linked list of ClassPathEntry instances
   static ClassPathEntry* _last_entry;
   static int _num_entries;
 
-  // Hash table used to keep track of loaded packages
-  static PackageHashtable* _package_hash_table;
+  // Pointer into the linked list of ClassPathEntry instances.
+  // Marks the start of:
+  //   - the boot loader's append path
+  //     [-Xbootclasspath/a]; [jvmti appended entries]
+  static ClassPathEntry* _first_append_entry;
+
   static const char* _shared_archive;
 
+  // True if the boot path has a "modules" jimage
+  static bool _has_jimage;
+
+  // Array of module names associated with the boot class loader
+  CDS_ONLY(static GrowableArray<char*>* _boot_modules_array;)
+
+  // Array of module names associated with the ext class loader
+  CDS_ONLY(static GrowableArray<char*>* _ext_modules_array;)
+
   // Info used by CDS
   CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
 
-  // Hash function
-  static unsigned int hash(const char *s, int n);
-  // Returns the package file name corresponding to the specified package
-  // or class name, or null if not found.
-  static PackageInfo* lookup_package(const char *pkgname);
-  // Adds a new package entry for the specified class or package name and
-  // corresponding directory or jar file name.
-  static bool add_package(const char *pkgname, int classpath_index, TRAPS);
-
   // Initialization
   static void setup_bootstrap_search_path();
-  static void setup_search_path(const char *class_path);
+  static void setup_search_path(const char *class_path, bool setting_bootstrap);
 
   static void load_zip_library();
   static void load_jimage_library();
   static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
                                                  bool throw_exception, TRAPS);
 
+ public:
+
+  // 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
+  // field so that get_system_package() will know to return a non-null value
+  // for the package's location.  And, so that the package will be added to
+  // the list of packages returned by get_system_packages().
+  // For packages whose classes are loaded from the boot loader class path, the
+  // classpath_index indicates which entry on the boot loader class path.
+  static bool add_package(const char *fullq_class_name, s2 classpath_index, TRAPS);
+
   // Canonicalizes path names, so strcmp will work properly. This is mainly
   // to avoid confusing the zip library
   static bool get_canonical_path(const char* orig, char* out, int len);
-
   static const char* file_name_for_class_name(const char* class_name,
                                               int class_name_len);
 
@@ -220,6 +247,8 @@
   static int crc32(int crc, const char* buf, int len);
   static bool update_class_path_entry_list(const char *path,
                                            bool check_for_duplicates,
+                                           bool mark_append_entry,
+                                           bool prepend_entry,
                                            bool throw_exception=true);
   static void print_bootclasspath();
 
@@ -284,8 +313,18 @@
     return _load_instance_class_failCounter;
   }
 
+  // Sets _has_jimage to TRUE if "modules" jimage file exists
+  static void set_has_jimage(bool val) {
+    _has_jimage = val;
+  }
+
+  static bool has_jimage() { return _has_jimage; }
+
+  // Create the ModuleEntry for java.base
+  static void create_javabase();
+
   // Load individual .class file
-  static instanceKlassHandle load_class(Symbol* class_name, TRAPS);
+  static instanceKlassHandle load_class(Symbol* class_name, bool search_append_only, TRAPS);
 
   // If the specified package has been loaded by the system, then returns
   // the name of the directory or ZIP file that the package was loaded from.
@@ -304,9 +343,7 @@
   // Initialization
   static void initialize();
   CDS_ONLY(static void initialize_shared_path();)
-  static void create_package_info_table();
-  static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
-                                        int number_of_entries);
+
   static int compute_Object_vtable();
 
   static ClassPathEntry* classpath_entry(int n) {
@@ -320,8 +357,6 @@
 
 #if INCLUDE_CDS
   // Sharing dump and restore
-  static void copy_package_info_buckets(char** top, char* end);
-  static void copy_package_info_table(char** top, char* end);
 
   static void  check_shared_classpath(const char *path);
   static void  finalize_shared_paths_misc_info();
@@ -329,7 +364,12 @@
   static void* get_shared_paths_misc_info();
   static bool  check_shared_paths_misc_info(void* info, int size);
   static void  exit_with_path_failure(const char* error, const char* message);
+
+  static jshort module_to_classloader(const char* module_name);
+  static void initialize_module_loader_map(JImageFile* jimage);
 #endif
+  static jshort classloader_type(Symbol* class_name, ClassPathEntry* e,
+                                 int classpath_index, TRAPS);
 
   static void  trace_class_path(outputStream* out, const char* msg, const char* name = NULL);
 
@@ -342,15 +382,30 @@
   static jlong class_link_count();
   static jlong class_link_time_ms();
 
+  static void set_first_append_entry(ClassPathEntry* entry);
+
   // indicates if class path already contains a entry (exact match by name)
   static bool contains_entry(ClassPathEntry* entry);
 
   // adds a class path list
   static void add_to_list(ClassPathEntry* new_entry);
 
+  // prepends a class path list
+  static void prepend_to_list(ClassPathEntry* new_entry);
+
   // creates a class path zip entry (returns NULL if JAR file cannot be opened)
   static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
 
+  // add a path to class path list
+  static void add_to_list(const char* apath);
+
+  // prepend a path to class path list
+  static void prepend_to_list(const char* apath);
+
+  static bool string_ends_with(const char* str, const char* str_to_find);
+
+  static bool is_jrt(const char* name) { return string_ends_with(name, MODULES_IMAGE_NAME); }
+
   // Debugging
   static void verify()              PRODUCT_RETURN;
 
--- a/src/share/vm/classfile/classLoaderData.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classLoaderData.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -51,6 +51,8 @@
 #include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.hpp"
 #include "classfile/metadataOnStackMark.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
 #include "gc/shared/gcLocker.hpp"
@@ -81,6 +83,7 @@
   // The null-class-loader should always be kept alive.
   _keep_alive(is_anonymous || h_class_loader.is_null()),
   _metaspace(NULL), _unloading(false), _klasses(NULL),
+  _modules(NULL), _packages(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
   _next(NULL), _dependencies(dependencies), _shared_class_loader_id(-1),
   _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true,
@@ -166,6 +169,30 @@
   }
 }
 
+void ClassLoaderData::modules_do(void f(ModuleEntry*)) {
+  if (_modules != NULL) {
+    for (int i = 0; i < _modules->table_size(); i++) {
+      for (ModuleEntry* entry = _modules->bucket(i);
+                              entry != NULL;
+                              entry = entry->next()) {
+        f(entry);
+      }
+    }
+  }
+}
+
+void ClassLoaderData::packages_do(void f(PackageEntry*)) {
+  if (_packages != NULL) {
+    for (int i = 0; i < _packages->table_size(); i++) {
+      for (PackageEntry* entry = _packages->bucket(i);
+                              entry != NULL;
+                              entry = entry->next()) {
+        f(entry);
+      }
+    }
+  }
+}
+
 void ClassLoaderData::record_dependency(const Klass* k, TRAPS) {
   assert(k != NULL, "invariant");
 
@@ -338,6 +365,46 @@
   }
 }
 
+PackageEntryTable* ClassLoaderData::packages() {
+  // Lazily create the package entry table at first request.
+  if (_packages == NULL) {
+    MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
+    // Check again if _packages has been allocated while we were getting this lock.
+    if (_packages != NULL) {
+      return _packages;
+    }
+    // Ensure _packages is stable, since it is examined without a lock
+    OrderAccess::storestore();
+    _packages = new PackageEntryTable(PackageEntryTable::_packagetable_entry_size);
+  }
+  return _packages;
+}
+
+ModuleEntryTable* ClassLoaderData::modules() {
+  // Lazily create the module entry table at first request.
+  if (_modules == NULL) {
+    MutexLocker m1(Module_lock);
+    // Check again if _modules has been allocated while we were getting this lock.
+    if (_modules != NULL) {
+      return _modules;
+    }
+
+    ModuleEntryTable* temp_table = new ModuleEntryTable(ModuleEntryTable::_moduletable_entry_size);
+    // Each loader has one unnamed module entry. Create it before
+    // any classes, loaded by this loader, are defined in case
+    // they end up being defined in loader's unnamed module.
+    temp_table->create_unnamed_module(this);
+
+    {
+      MutexLockerEx m1(metaspace_lock(), Mutex::_no_safepoint_check_flag);
+      // Ensure _modules is stable, since it is examined without a lock
+      OrderAccess::storestore();
+      _modules = temp_table;
+    }
+  }
+  return _modules;
+}
+
 oop ClassLoaderData::keep_alive_object() const {
   assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
   return is_anonymous() ? _klasses->java_mirror() : class_loader();
@@ -355,6 +422,20 @@
   // Release C heap structures for all the classes.
   classes_do(InstanceKlass::release_C_heap_structures);
 
+  // Release C heap allocated hashtable for all the packages.
+  if (_packages != NULL) {
+    // Destroy the table itself
+    delete _packages;
+    _packages = NULL;
+  }
+
+  // Release C heap allocated hashtable for all the modules.
+  if (_modules != NULL) {
+    // Destroy the table itself
+    delete _modules;
+    _modules = NULL;
+  }
+
   Metaspace *m = _metaspace;
   if (m != NULL) {
     _metaspace = NULL;
@@ -435,6 +516,10 @@
   return handles()->allocate_handle(h());
 }
 
+void ClassLoaderData::remove_handle(jobject h) {
+  _handles->release_handle(h);
+}
+
 // Add this metadata pointer to be freed when it's safe.  This is only during
 // class unloading because Handles might point to this metadata field.
 void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
@@ -683,6 +768,40 @@
   }
 }
 
+void ClassLoaderDataGraph::modules_do(void f(ModuleEntry*)) {
+  assert_locked_or_safepoint(Module_lock);
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    cld->modules_do(f);
+  }
+}
+
+void ClassLoaderDataGraph::modules_unloading_do(void f(ModuleEntry*)) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  // Only walk the head until any clds not purged from prior unloading
+  // (CMS doesn't purge right away).
+  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
+    cld->modules_do(f);
+  }
+}
+
+void ClassLoaderDataGraph::packages_do(void f(PackageEntry*)) {
+  assert_locked_or_safepoint(Module_lock);
+  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
+    cld->packages_do(f);
+  }
+}
+
+void ClassLoaderDataGraph::packages_unloading_do(void f(PackageEntry*)) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
+  // Only walk the head until any clds not purged from prior unloading
+  // (CMS doesn't purge right away).
+  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
+    cld->packages_do(f);
+  }
+}
+
 void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
   for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
     cld->loaded_classes_do(klass_closure);
@@ -694,6 +813,7 @@
   // Only walk the head until any clds not purged from prior unloading
   // (CMS doesn't purge right away).
   for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
+    assert(cld->is_unloading(), "invariant");
     cld->classes_do(f);
   }
 }
@@ -770,6 +890,12 @@
   data = _head;
   while (data != NULL) {
     if (data->is_alive(is_alive_closure)) {
+      if (data->packages_defined()) {
+        data->packages()->purge_all_package_exports();
+      }
+      if (data->modules_defined()) {
+        data->modules()->purge_all_module_reads();
+      }
       // clean metaspace
       if (walk_all_metadata) {
         data->classes_do(InstanceKlass::purge_previous_versions);
@@ -962,6 +1088,7 @@
 Ticks ClassLoaderDataGraph::_class_unload_time;
 
 void ClassLoaderDataGraph::class_unload_event(Klass* const k) {
+  assert(k != NULL, "invariant");
 
   // post class unload event
   EventClassUnload event(UNTIMED);
--- a/src/share/vm/classfile/classLoaderData.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classLoaderData.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -53,6 +53,10 @@
 class JNIMethodBlock;
 class JNIHandleBlock;
 class Metadebug;
+class ModuleEntry;
+class PackageEntry;
+class ModuleEntryTable;
+class PackageEntryTable;
 
 // GC root for walking class loader data created
 
@@ -92,6 +96,10 @@
   static void classes_do(KlassClosure* klass_closure);
   static void classes_do(void f(Klass* const));
   static void methods_do(void f(Method*));
+  static void modules_do(void f(ModuleEntry*));
+  static void modules_unloading_do(void f(ModuleEntry*));
+  static void packages_do(void f(PackageEntry*));
+  static void packages_unloading_do(void f(PackageEntry*));
   static void loaded_classes_do(KlassClosure* klass_closure);
   static void classes_unloading_do(void f(Klass* const));
   static bool do_unloading(BoolObjectClosure* is_alive, bool clean_previous_versions);
@@ -171,9 +179,12 @@
   volatile int _claimed;   // true if claimed, for example during GC traces.
                            // To avoid applying oop closure more than once.
                            // Has to be an int because we cas it.
+  JNIHandleBlock* _handles; // Handles to constant pool arrays, Modules, etc, which
+                            // have the same life cycle of the corresponding ClassLoader.
+
   Klass* _klasses;         // The classes defined by the class loader.
-
-  JNIHandleBlock* _handles; // Handles to constant pool arrays
+  PackageEntryTable* _packages; // The packages defined by the class loader.
+  ModuleEntryTable* _modules;   // The modules defined by the class loader.
 
   // These method IDs are created for the class loader and set to NULL when the
   // class loader is unloaded.  They are rarely freed, only for redefine classes
@@ -217,6 +228,8 @@
   void loaded_classes_do(KlassClosure* klass_closure);
   void classes_do(void f(InstanceKlass*));
   void methods_do(void f(Method*));
+  void modules_do(void f(ModuleEntry*));
+  void packages_do(void f(PackageEntry*));
 
   // Deallocate free list during class unloading.
   void free_deallocate_list();
@@ -292,11 +305,16 @@
   const char* loader_name();
 
   jobject add_handle(Handle h);
+  void remove_handle(jobject h);
   void add_class(Klass* k, bool publicize = true);
   void remove_class(Klass* k);
   bool contains_klass(Klass* k);
   void record_dependency(const Klass* to, TRAPS);
   void init_dependencies(TRAPS);
+  PackageEntryTable* packages();
+  bool packages_defined() { return (_packages != NULL); }
+  ModuleEntryTable* modules();
+  bool modules_defined() { return (_modules != NULL); }
 
   void add_to_deallocate_list(Metadata* m);
 
--- a/src/share/vm/classfile/classLoaderExt.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/classLoaderExt.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -49,12 +49,14 @@
       return false;
     }
 
-    instanceKlassHandle record_result(const int classpath_index,
+    instanceKlassHandle record_result(const s2 classpath_index,
+                                      const jshort classloader_type,
                                       const ClassPathEntry* e,
                                       instanceKlassHandle result, TRAPS) {
       if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
         if (DumpSharedSpaces) {
           result->set_shared_classpath_index(classpath_index);
+          result->set_class_loader_type(classloader_type);
         }
         return result;
       } else {
@@ -65,13 +67,27 @@
 
 
   static void add_class_path_entry(const char* path, bool check_for_duplicates,
-                                   ClassPathEntry* new_entry) {
-    ClassLoader::add_to_list(new_entry);
+                                   ClassPathEntry* new_entry, bool prepend_entry) {
+    if (prepend_entry) {
+      ClassLoader::prepend_to_list(new_entry);
+    } else {
+      ClassLoader::add_to_list(new_entry);
+    }
   }
   static void append_boot_classpath(ClassPathEntry* new_entry) {
     ClassLoader::add_to_list(new_entry);
+    // During jvmti live phase an entry can be appended to the boot
+    // loader's ClassPathEntry instances.  Need to mark the start
+    // of the boot loader's append path in case there was no reason
+    // to mark it initially in setup_bootstrap_search_path.
+    if (ClassLoader::_first_append_entry == NULL) {
+      ClassLoader::set_first_append_entry(new_entry);
+    }
   }
   static void setup_search_paths() {}
+  static bool is_boot_classpath(int classpath_index) {
+   return true;
+ }
   static Klass* load_one_class(ClassListParser* parser, TRAPS);
 };
 
--- a/src/share/vm/classfile/javaClasses.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/javaClasses.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,7 +24,9 @@
 
 #include "precompiled.hpp"
 #include "classfile/altHashing.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/debugInfo.hpp"
@@ -768,7 +770,7 @@
       }
     }
   }
-  create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
+  create_mirror(k, Handle(NULL), Handle(NULL), Handle(NULL), CHECK);
 }
 
 void java_lang_Class::initialize_mirror_fields(KlassHandle k,
@@ -789,7 +791,7 @@
 }
 
 void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
-                                    Handle protection_domain, TRAPS) {
+                                    Handle module, Handle protection_domain, TRAPS) {
   assert(k->java_mirror() == NULL, "should only assign mirror once");
   // Use this moment of initialization to cache modifier_flags also,
   // to support Class.getModifiers().  Instance classes recalculate
@@ -849,11 +851,25 @@
     assert(class_loader() == k->class_loader(), "should be same");
     set_class_loader(mirror(), class_loader());
 
+    // set the module field in the java_lang_Class instance
+    // This may be null during bootstrap but will get fixed up later on.
+    set_module(mirror(), module());
+
     // Setup indirection from klass->mirror last
     // after any exceptions can happen during allocations.
     if (!k.is_null()) {
       k->set_java_mirror(mirror());
     }
+
+    // Keep list of classes needing java.base module fixup.
+    if (!ModuleEntryTable::javabase_defined()) {
+      if (fixup_modulefield_list() == NULL) {
+        GrowableArray<Klass*>* list =
+          new (ResourceObj::C_HEAP, mtClass) GrowableArray<Klass*>(500, true);
+        set_fixup_modulefield_list(list);
+      }
+      fixup_modulefield_list()->push(k());
+    }
   } else {
     if (fixup_mirror_list() == NULL) {
       GrowableArray<Klass*>* list =
@@ -864,6 +880,10 @@
   }
 }
 
+void java_lang_Class::fixup_modulefield(KlassHandle k, Handle module) {
+  assert(_module_offset != 0, "must have been computed already");
+  java_lang_Class::set_module(k->java_mirror(), module());
+}
 
 int  java_lang_Class::oop_size(oop java_class) {
   assert(_oop_size_offset != 0, "must be set");
@@ -931,6 +951,16 @@
   return java_class->obj_field(_class_loader_offset);
 }
 
+oop java_lang_Class::module(oop java_class) {
+  assert(_module_offset != 0, "must be set");
+  return java_class->obj_field(_module_offset);
+}
+
+void java_lang_Class::set_module(oop java_class, oop module) {
+  assert(_module_offset != 0, "must be set");
+  java_class->obj_field_put(_module_offset, module);
+}
+
 oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
   // This should be improved by adding a field at the Java level or by
   // introducing a new VM klass (see comment in ClassFileParser)
@@ -1116,6 +1146,10 @@
                  k, vmSymbols::componentType_name(),
                  vmSymbols::class_signature());
 
+  compute_offset(_module_offset,
+                 k, vmSymbols::module_name(),
+                 vmSymbols::module_signature());
+
   // Init lock is a C union with component_mirror.  Only instanceKlass mirrors have
   // init_lock and only ArrayKlass mirrors have component_mirror.  Since both are oops
   // GC treats them the same.
@@ -1668,28 +1702,48 @@
     buf_len += (int)strlen(source_file_name);
   }
 
+  char *module_name = NULL, *module_version = NULL;
+  ModuleEntry* module = holder->module();
+  if (module->is_named()) {
+    module_name = module->name()->as_C_string();
+    buf_len += (int)strlen(module_name);
+    if (module->version() != NULL) {
+      module_version = module->version()->as_C_string();
+      buf_len += (int)strlen(module_version);
+    }
+  }
+
   // Allocate temporary buffer with extra space for formatting and line number
   char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
 
   // Print stack trace line in buffer
-  sprintf(buf, "\tat %s.%s", klass_name, method_name);
+  sprintf(buf, "\tat %s.%s(", klass_name, method_name);
+
+  // Print module information
+  if (module_name != NULL) {
+    if (module_version != NULL) {
+      sprintf(buf + (int)strlen(buf), "%s@%s/", module_name, module_version);
+    } else {
+      sprintf(buf + (int)strlen(buf), "%s/", module_name);
+    }
+  }
 
   if (!version_matches(method, version)) {
-    strcat(buf, "(Redefined)");
+    strcat(buf, "Redefined)");
   } else {
     int line_number = Backtrace::get_line_number(method, bci);
     if (line_number == -2) {
-      strcat(buf, "(Native Method)");
+      strcat(buf, "Native Method)");
     } else {
       if (source_file_name != NULL && (line_number != -1)) {
         // Sourcename and linenumber
-        sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number);
+        sprintf(buf + (int)strlen(buf), "%s:%d)", source_file_name, line_number);
       } else if (source_file_name != NULL) {
         // Just sourcename
-        sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
+        sprintf(buf + (int)strlen(buf), "%s)", source_file_name);
       } else {
         // Neither sourcename nor linenumber
-        sprintf(buf + (int)strlen(buf), "(Unknown Source)");
+        sprintf(buf + (int)strlen(buf), "Unknown Source)");
       }
       nmethod* nm = method->code();
       if (WizardMode && nm != NULL) {
@@ -2094,6 +2148,20 @@
   oop methodname = StringTable::intern(sym, CHECK_0);
   java_lang_StackTraceElement::set_methodName(element(), methodname);
 
+  // Fill in module name and version
+  ModuleEntry* module = holder->module();
+  if (module->is_named()) {
+    oop module_name = StringTable::intern(module->name(), CHECK_0);
+    java_lang_StackTraceElement::set_moduleName(element(), module_name);
+    oop module_version;
+    if (module->version() != NULL) {
+      module_version = StringTable::intern(module->version(), CHECK_0);
+    } else {
+      module_version = NULL;
+    }
+    java_lang_StackTraceElement::set_moduleVersion(element(), module_version);
+  }
+
   if (!version_matches(method, version)) {
     // The method was redefined, accurate line number information isn't available
     java_lang_StackTraceElement::set_fileName(element(), NULL);
@@ -2753,6 +2821,80 @@
 }
 
 
+int java_lang_reflect_Module::loader_offset;
+int java_lang_reflect_Module::name_offset;
+int java_lang_reflect_Module::_module_entry_offset = -1;
+
+Handle java_lang_reflect_Module::create(Handle loader, Handle module_name, TRAPS) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+
+  Symbol* name = vmSymbols::java_lang_reflect_Module();
+  Klass* k = SystemDictionary::resolve_or_fail(name, true, CHECK_NH);
+  instanceKlassHandle klass (THREAD, k);
+
+  Handle jlrmh = klass->allocate_instance_handle(CHECK_NH);
+  JavaValue result(T_VOID);
+  JavaCalls::call_special(&result, jlrmh, KlassHandle(THREAD, klass()),
+                          vmSymbols::object_initializer_name(),
+                          vmSymbols::java_lang_reflect_module_init_signature(),
+                          loader, module_name, CHECK_NH);
+  return jlrmh;
+}
+
+void java_lang_reflect_Module::compute_offsets() {
+  Klass* k = SystemDictionary::reflect_Module_klass();
+  if(NULL != k) {
+    compute_offset(loader_offset,  k, vmSymbols::loader_name(),  vmSymbols::classloader_signature());
+    compute_offset(name_offset,    k, vmSymbols::name_name(),    vmSymbols::string_signature());
+    MODULE_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
+  }
+}
+
+
+oop java_lang_reflect_Module::loader(oop module) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  return module->obj_field(loader_offset);
+}
+
+void java_lang_reflect_Module::set_loader(oop module, oop value) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  module->obj_field_put(loader_offset, value);
+}
+
+oop java_lang_reflect_Module::name(oop module) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  return module->obj_field(name_offset);
+}
+
+void java_lang_reflect_Module::set_name(oop module, oop value) {
+  assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
+  module->obj_field_put(name_offset, value);
+}
+
+ModuleEntry* java_lang_reflect_Module::module_entry(oop module, TRAPS) {
+  assert(_module_entry_offset != -1, "Uninitialized module_entry_offset");
+  assert(module != NULL, "module can't be null");
+  assert(module->is_oop(), "module must be oop");
+
+  ModuleEntry* module_entry = (ModuleEntry*)module->address_field(_module_entry_offset);
+  if (module_entry == NULL) {
+    // If the inject field containing the ModuleEntry* is null then return the
+    // class loader's unnamed module.
+    oop loader = java_lang_reflect_Module::loader(module);
+    Handle h_loader = Handle(THREAD, loader);
+    ClassLoaderData* loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
+    return loader_cld->modules()->unnamed_module();
+  }
+  return module_entry;
+}
+
+void java_lang_reflect_Module::set_module_entry(oop module, ModuleEntry* module_entry) {
+  assert(_module_entry_offset != -1, "Uninitialized module_entry_offset");
+  assert(module != NULL, "module can't be null");
+  assert(module->is_oop(), "module must be oop");
+  module->address_field_put(_module_entry_offset, (address)module_entry);
+}
+
 Handle sun_reflect_ConstantPool::create(TRAPS) {
   assert(Universe::is_fully_initialized(), "Need to find another solution to the reflection problem");
   Klass* k = SystemDictionary::reflect_ConstantPool_klass();
@@ -3352,6 +3494,7 @@
 bool java_lang_ClassLoader::offsets_computed = false;
 int  java_lang_ClassLoader::_loader_data_offset = -1;
 int  java_lang_ClassLoader::parallelCapable_offset = -1;
+int  java_lang_ClassLoader::unnamedModule_offset = -1;
 
 ClassLoaderData** java_lang_ClassLoader::loader_data_addr(oop loader) {
     assert(loader != NULL && loader->is_oop(), "loader must be oop");
@@ -3371,6 +3514,9 @@
   compute_optional_offset(parallelCapable_offset,
     k1, vmSymbols::parallelCapable_name(), vmSymbols::concurrenthashmap_signature());
 
+  compute_offset(unnamedModule_offset,
+    k1, vmSymbols::unnamedModule_name(), vmSymbols::module_signature());
+
   CLASSLOADER_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
 }
 
@@ -3438,6 +3584,10 @@
   return loader;
 }
 
+oop java_lang_ClassLoader::unnamedModule(oop loader) {
+  assert(is_instance(loader), "loader must be oop");
+  return loader->obj_field(unnamedModule_offset);
+}
 
 // Support for java_lang_System
 int java_lang_System::in_offset_in_bytes() {
@@ -3470,11 +3620,13 @@
 int java_lang_Class::_oop_size_offset;
 int java_lang_Class::_static_oop_field_count_offset;
 int java_lang_Class::_class_loader_offset;
+int java_lang_Class::_module_offset;
 int java_lang_Class::_protection_domain_offset;
 int java_lang_Class::_component_mirror_offset;
 int java_lang_Class::_init_lock_offset;
 int java_lang_Class::_signers_offset;
 GrowableArray<Klass*>* java_lang_Class::_fixup_mirror_list = NULL;
+GrowableArray<Klass*>* java_lang_Class::_fixup_modulefield_list = NULL;
 int java_lang_Throwable::backtrace_offset;
 int java_lang_Throwable::detailMessage_offset;
 int java_lang_Throwable::cause_offset;
@@ -3534,6 +3686,8 @@
 int java_lang_StackTraceElement::methodName_offset;
 int java_lang_StackTraceElement::fileName_offset;
 int java_lang_StackTraceElement::lineNumber_offset;
+int java_lang_StackTraceElement::moduleName_offset;
+int java_lang_StackTraceElement::moduleVersion_offset;
 int java_lang_StackFrameInfo::_declaringClass_offset;
 int java_lang_StackFrameInfo::_memberName_offset;
 int java_lang_StackFrameInfo::_bci_offset;
@@ -3575,6 +3729,14 @@
   element->int_field_put(lineNumber_offset, value);
 }
 
+void java_lang_StackTraceElement::set_moduleName(oop element, oop value) {
+  element->obj_field_put(moduleName_offset, value);
+}
+
+void java_lang_StackTraceElement::set_moduleVersion(oop element, oop value) {
+  element->obj_field_put(moduleVersion_offset, value);
+}
+
 // Support for java_lang_StackFrameInfo
 void java_lang_StackFrameInfo::set_declaringClass(oop element, oop value) {
   element->obj_field_put(_declaringClass_offset, value);
@@ -3713,6 +3875,8 @@
   java_lang_System::static_security_offset = java_lang_System::hc_static_security_offset * x;
 
   // java_lang_StackTraceElement
+  java_lang_StackTraceElement::moduleName_offset = java_lang_StackTraceElement::hc_moduleName_offset * x + header;
+  java_lang_StackTraceElement::moduleVersion_offset = java_lang_StackTraceElement::hc_moduleVersion_offset * x + header;
   java_lang_StackTraceElement::declaringClass_offset = java_lang_StackTraceElement::hc_declaringClass_offset  * x + header;
   java_lang_StackTraceElement::methodName_offset = java_lang_StackTraceElement::hc_methodName_offset * x + header;
   java_lang_StackTraceElement::fileName_offset   = java_lang_StackTraceElement::hc_fileName_offset   * x + header;
@@ -3752,6 +3916,7 @@
   sun_reflect_ConstantPool::compute_offsets();
   sun_reflect_UnsafeStaticFieldAccessorImpl::compute_offsets();
   java_lang_reflect_Parameter::compute_offsets();
+  java_lang_reflect_Module::compute_offsets();
   java_lang_StackFrameInfo::compute_offsets();
   java_lang_LiveStackFrameInfo::compute_offsets();
 
@@ -3899,7 +4064,7 @@
 
   // java.lang.ClassLoader
 
-  CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent,      "Ljava/lang/ClassLoader;");
+  CHECK_OFFSET("java/lang/ClassLoader", java_lang_ClassLoader, parent,        "Ljava/lang/ClassLoader;");
 
   // java.lang.System
 
--- a/src/share/vm/classfile/javaClasses.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -210,12 +210,14 @@
   static int _init_lock_offset;
   static int _signers_offset;
   static int _class_loader_offset;
+  static int _module_offset;
   static int _component_mirror_offset;
 
   static bool offsets_computed;
   static int classRedefinedCount_offset;
 
   static GrowableArray<Klass*>* _fixup_mirror_list;
+  static GrowableArray<Klass*>* _fixup_modulefield_list;
 
   static void set_init_lock(oop java_class, oop init_lock);
   static void set_protection_domain(oop java_class, oop protection_domain);
@@ -226,10 +228,13 @@
   static void compute_offsets();
 
   // Instance creation
-  static void create_mirror(KlassHandle k, Handle class_loader,
+  static void create_mirror(KlassHandle k, Handle class_loader, Handle module,
                             Handle protection_domain, TRAPS);
   static void fixup_mirror(KlassHandle k, TRAPS);
   static oop  create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS);
+
+  static void fixup_modulefield(KlassHandle k, Handle module);
+
   // Conversion
   static Klass* as_Klass(oop java_class);
   static void set_klass(oop java_class, Klass* klass);
@@ -267,18 +272,29 @@
   static void set_signers(oop java_class, objArrayOop signers);
 
   static oop class_loader(oop java_class);
+  static void set_module(oop java_class, oop module);
+  static oop module(oop java_class);
 
   static int oop_size(oop java_class);
   static void set_oop_size(oop java_class, int size);
   static int static_oop_field_count(oop java_class);
   static void set_static_oop_field_count(oop java_class, int size);
 
+
   static GrowableArray<Klass*>* fixup_mirror_list() {
     return _fixup_mirror_list;
   }
   static void set_fixup_mirror_list(GrowableArray<Klass*>* v) {
     _fixup_mirror_list = v;
   }
+
+  static GrowableArray<Klass*>* fixup_modulefield_list() {
+    return _fixup_modulefield_list;
+  }
+  static void set_fixup_modulefield_list(GrowableArray<Klass*>* v) {
+    _fixup_modulefield_list = v;
+  }
+
   // Debugging
   friend class JavaClasses;
   friend class InstanceKlass;   // verification code accesses offsets
@@ -758,6 +774,39 @@
   friend class JavaClasses;
 };
 
+#define MODULE_INJECTED_FIELDS(macro)                            \
+  macro(java_lang_reflect_Module, module_entry, intptr_signature, false)
+
+class java_lang_reflect_Module {
+  private:
+    static int loader_offset;
+    static int name_offset;
+    static int _module_entry_offset;
+    static void compute_offsets();
+
+  public:
+    // Allocation
+    static Handle create(Handle loader, Handle module_name, TRAPS);
+
+    // Testers
+    static bool is_subclass(Klass* klass) {
+      return klass->is_subclass_of(SystemDictionary::reflect_Module_klass());
+    }
+    static bool is_instance(oop obj);
+
+    // Accessors
+    static oop loader(oop module);
+    static void set_loader(oop module, oop value);
+
+    static oop name(oop module);
+    static void set_name(oop module, oop value);
+
+    static ModuleEntry* module_entry(oop module, TRAPS);
+    static void set_module_entry(oop module, ModuleEntry* module_entry);
+
+  friend class JavaClasses;
+};
+
 // Interface to sun.reflect.ConstantPool objects
 class sun_reflect_ConstantPool {
  private:
@@ -1203,6 +1252,7 @@
   static bool offsets_computed;
   static int parent_offset;
   static int parallelCapable_offset;
+  static int unnamedModule_offset;
 
  public:
   static void compute_offsets();
@@ -1227,6 +1277,8 @@
   }
   static bool is_instance(oop obj);
 
+  static oop unnamedModule(oop loader);
+
   // Debugging
   friend class JavaClasses;
   friend class ClassFileParser; // access to number_of_fake_fields
@@ -1266,12 +1318,16 @@
 class java_lang_StackTraceElement: AllStatic {
  private:
   enum {
-    hc_declaringClass_offset  = 0,
-    hc_methodName_offset = 1,
-    hc_fileName_offset   = 2,
-    hc_lineNumber_offset = 3
+    hc_moduleName_offset = 0,
+    hc_moduleVersion_offset = 1,
+    hc_declaringClass_offset = 2,
+    hc_methodName_offset = 3,
+    hc_fileName_offset   = 4,
+    hc_lineNumber_offset = 5
   };
 
+  static int moduleName_offset;
+  static int moduleVersion_offset;
   static int declaringClass_offset;
   static int methodName_offset;
   static int fileName_offset;
@@ -1279,6 +1335,8 @@
 
  public:
   // Setters
+  static void set_moduleName(oop element, oop value);
+  static void set_moduleVersion(oop element, oop value);
   static void set_declaringClass(oop element, oop value);
   static void set_methodName(oop element, oop value);
   static void set_fileName(oop element, oop value);
@@ -1456,8 +1514,8 @@
   CLASSLOADER_INJECTED_FIELDS(macro)        \
   MEMBERNAME_INJECTED_FIELDS(macro)         \
   CALLSITECONTEXT_INJECTED_FIELDS(macro)    \
-  STACKFRAMEINFO_INJECTED_FIELDS(macro)
-
+  STACKFRAMEINFO_INJECTED_FIELDS(macro)     \
+  MODULE_INJECTED_FIELDS(macro)
 
 // Interface to hard-coded offset checking
 
--- a/src/share/vm/classfile/javaClasses.inline.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/javaClasses.inline.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -171,6 +171,10 @@
 
 
 
+inline bool java_lang_reflect_Module::is_instance(oop obj) {
+  return obj != NULL && is_subclass(obj->klass());
+}
+
 inline int Backtrace::merge_bci_and_version(int bci, int version) {
   // only store u2 for version, checking for overflow.
   if (version > USHRT_MAX || version < 0) version = USHRT_MAX;
--- a/src/share/vm/classfile/jimage.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/jimage.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,7 +22,7 @@
  *
  */
 
-#include "jni.h"
+#include "prims/jni.h"
 
 // Opaque reference to a JImage file.
 class JImageFile;
@@ -35,6 +35,8 @@
 
 // JImage Error Codes
 
+// Resource was not found
+#define JIMAGE_NOT_FOUND (0)
 // The image file is not prefixed with 0xCAFEDADA
 #define JIMAGE_BAD_MAGIC (-1)
 // The image file does not have a compatible (translatable) version
@@ -55,7 +57,7 @@
  *
  *  Ex.
  *   jint error;
- *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules/bootmodules.jimage", &error);
+ *   JImageFile* jimage = (*JImageOpen)(JAVA_HOME "lib/modules", &error);
  *   if (image == NULL) {
  *     tty->print_cr("JImage failed to open: %d", error);
  *     ...
--- a/src/share/vm/classfile/klassFactory.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/klassFactory.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -102,11 +102,15 @@
   assert(loader_data != NULL, "invariant");
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
 
+  bool cf_changed_in_CFLH = false;
+
   ResourceMark rm;
   HandleMark hm;
 
   JvmtiCachedClassFileData* cached_class_file = NULL;
 
+  ClassFileStream* old_stream = stream;
+
   stream = prologue(stream,
                     name,
                     loader_data,
@@ -124,8 +128,8 @@
                          ClassFileParser::BROADCAST, // publicity level
                          CHECK_NULL);
 
-  instanceKlassHandle result = parser.create_instance_klass(CHECK_NULL);
-  assert(result == parser.create_instance_klass(THREAD), "invariant");
+  instanceKlassHandle result = parser.create_instance_klass(old_stream != stream, CHECK_NULL);
+  assert(result == parser.create_instance_klass(old_stream != stream, THREAD), "invariant");
 
   if (result.is_null()) {
     return NULL;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/moduleEntry.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,391 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/classLoaderData.hpp"
+#include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "logging/log.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/symbol.hpp"
+#include "prims/jni.h"
+#include "runtime/handles.inline.hpp"
+#include "runtime/safepoint.hpp"
+#include "trace/traceMacros.hpp"
+#include "utilities/events.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.inline.hpp"
+
+ModuleEntry* ModuleEntryTable::_javabase_module = NULL;
+
+// Returns the shared ProtectionDomain
+Handle ModuleEntry::shared_protection_domain() {
+  return Handle(JNIHandles::resolve(_pd));
+}
+
+// Set the shared ProtectionDomain atomically
+void ModuleEntry::set_shared_protection_domain(ClassLoaderData *loader_data,
+                                               Handle pd_h) {
+  // Create a JNI handle for the shared ProtectionDomain and save it atomically.
+  // If someone beats us setting the _pd cache, the created JNI handle is destroyed.
+  jobject obj = loader_data->add_handle(pd_h);
+  if (Atomic::cmpxchg_ptr(obj, &_pd, NULL) != NULL) {
+    loader_data->remove_handle(obj);
+  }
+}
+
+// Returns true if this module can read module m
+bool ModuleEntry::can_read(ModuleEntry* m) const {
+  assert(m != NULL, "No module to lookup in this module's reads list");
+  if (!this->is_named()) return true; // Unnamed modules read everyone.
+  MutexLocker m1(Module_lock);
+  if (_reads == NULL) {
+    return false;
+  } else {
+    return _reads->contains(m);
+  }
+}
+
+// Add a new module to this module's reads list
+void ModuleEntry::add_read(ModuleEntry* m) {
+  MutexLocker m1(Module_lock);
+  if (m == NULL) {
+    set_can_read_all_unnamed();
+  } else {
+    if (_reads == NULL) {
+      // Lazily create a module's reads list
+      _reads = new (ResourceObj::C_HEAP, mtClass)GrowableArray<ModuleEntry*>(MODULE_READS_SIZE, true);
+    }
+    _reads->append_if_missing(m);
+  }
+}
+
+bool ModuleEntry::has_reads() const {
+  return _reads != NULL && !_reads->is_empty();
+}
+
+// Purge dead module entries out of reads list.
+void ModuleEntry::purge_reads() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  if (_reads != NULL) {
+    // Go backwards because this removes entries that are dead.
+    int len = _reads->length();
+    for (int idx = len - 1; idx >= 0; idx--) {
+      ModuleEntry* module_idx = _reads->at(idx);
+      ClassLoaderData* cld = module_idx->loader();
+      if (cld->is_unloading()) {
+        _reads->delete_at(idx);
+      }
+    }
+  }
+}
+
+void ModuleEntry::module_reads_do(ModuleClosure* const f) {
+  assert_locked_or_safepoint(Module_lock);
+  assert(f != NULL, "invariant");
+
+  if (_reads != NULL) {
+    int reads_len = _reads->length();
+    for (int i = 0; i < reads_len; ++i) {
+      f->do_module(_reads->at(i));
+    }
+  }
+}
+
+void ModuleEntry::delete_reads() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  delete _reads;
+  _reads = NULL;
+}
+
+ModuleEntryTable::ModuleEntryTable(int table_size)
+  : Hashtable<Symbol*, mtClass>(table_size, sizeof(ModuleEntry)), _unnamed_module(NULL)
+{
+}
+
+ModuleEntryTable::~ModuleEntryTable() {
+  assert_locked_or_safepoint(Module_lock);
+
+  // Walk through all buckets and all entries in each bucket,
+  // freeing each entry.
+  for (int i = 0; i < table_size(); ++i) {
+    for (ModuleEntry* m = bucket(i); m != NULL;) {
+      ModuleEntry* to_remove = m;
+      // read next before freeing.
+      m = m->next();
+
+      ResourceMark rm;
+      log_debug(modules)("ModuleEntryTable: deleting module: %s", to_remove->name() != NULL ?
+                         to_remove->name()->as_C_string() : UNNAMED_MODULE);
+
+      // Clean out the C heap allocated reads list first before freeing the entry
+      to_remove->delete_reads();
+      if (to_remove->name() != NULL) {
+        to_remove->name()->decrement_refcount();
+      }
+      if (to_remove->version() != NULL) {
+        to_remove->version()->decrement_refcount();
+      }
+      if (to_remove->location() != NULL) {
+        to_remove->location()->decrement_refcount();
+      }
+
+      // Unlink from the Hashtable prior to freeing
+      unlink_entry(to_remove);
+      FREE_C_HEAP_ARRAY(char, to_remove);
+    }
+  }
+  assert(number_of_entries() == 0, "should have removed all entries");
+  assert(new_entry_free_list() == NULL, "entry present on ModuleEntryTable's free list");
+  free_buckets();
+}
+
+void ModuleEntryTable::create_unnamed_module(ClassLoaderData* loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+
+  // Each ModuleEntryTable has exactly one unnamed module
+  if (loader_data->is_the_null_class_loader_data()) {
+    // For the boot loader, the java.lang.reflect.Module for the unnamed module
+    // is not known until a call to JVM_SetBootLoaderUnnamedModule is made. At
+    // this point initially create the ModuleEntry for the unnamed module.
+    _unnamed_module = new_entry(0, Handle(NULL), NULL, NULL, NULL, loader_data);
+  } else {
+    // For all other class loaders the java.lang.reflect.Module for their
+    // corresponding unnamed module can be found in the java.lang.ClassLoader object.
+    oop module = java_lang_ClassLoader::unnamedModule(loader_data->class_loader());
+    _unnamed_module = new_entry(0, Handle(module), NULL, NULL, NULL, loader_data);
+
+    // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module
+    // object.
+    java_lang_reflect_Module::set_module_entry(module, _unnamed_module);
+  }
+
+  // Add to bucket 0, no name to hash on
+  add_entry(0, _unnamed_module);
+}
+
+ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle jlrM_handle, Symbol* name,
+                                         Symbol* version, Symbol* location,
+                                         ClassLoaderData* loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+  ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY2(char, entry_size(), mtClass, CURRENT_PC);
+
+  // Initialize everything BasicHashtable would
+  entry->set_next(NULL);
+  entry->set_hash(hash);
+  entry->set_literal(name);
+
+  // Initialize fields specific to a ModuleEntry
+  entry->init();
+  if (name != NULL) {
+    name->increment_refcount();
+  } else {
+    // Unnamed modules can read all other unnamed modules.
+    entry->set_can_read_all_unnamed();
+  }
+
+  if (!jlrM_handle.is_null()) {
+    entry->set_jlrM_module(loader_data->add_handle(jlrM_handle));
+  }
+
+  entry->set_loader(loader_data);
+  entry->set_version(version);
+  entry->set_location(location);
+
+  TRACE_INIT_MODULE_ID(entry);
+
+  return entry;
+}
+
+void ModuleEntryTable::add_entry(int index, ModuleEntry* new_entry) {
+  assert_locked_or_safepoint(Module_lock);
+  Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
+}
+
+ModuleEntry* ModuleEntryTable::locked_create_entry_or_null(Handle jlrM_handle,
+                                                           Symbol* module_name,
+                                                           Symbol* module_version,
+                                                           Symbol* module_location,
+                                                           ClassLoaderData* loader_data) {
+  assert(module_name != NULL, "ModuleEntryTable locked_create_entry_or_null should never be called for unnamed module.");
+  assert_locked_or_safepoint(Module_lock);
+  // Check if module already exists.
+  if (lookup_only(module_name) != NULL) {
+    return NULL;
+  } else {
+    ModuleEntry* entry = new_entry(compute_hash(module_name), jlrM_handle, module_name,
+                                   module_version, module_location, loader_data);
+    add_entry(index_for(module_name), entry);
+    return entry;
+  }
+}
+
+// lookup_only by Symbol* to find a ModuleEntry.
+ModuleEntry* ModuleEntryTable::lookup_only(Symbol* name) {
+  if (name == NULL) {
+    // Return this table's unnamed module
+    return unnamed_module();
+  }
+  int index = index_for(name);
+  for (ModuleEntry* m = bucket(index); m != NULL; m = m->next()) {
+    if (m->name()->fast_compare(name) == 0) {
+      return m;
+    }
+  }
+  return NULL;
+}
+
+// Remove dead modules from all other alive modules' reads list.
+// This should only occur at class unloading.
+void ModuleEntryTable::purge_all_module_reads() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  for (int i = 0; i < table_size(); i++) {
+    for (ModuleEntry* entry = bucket(i);
+                      entry != NULL;
+                      entry = entry->next()) {
+      entry->purge_reads();
+    }
+  }
+}
+
+void ModuleEntryTable::finalize_javabase(Handle jlrM_module, Symbol* version, Symbol* location) {
+  assert_locked_or_safepoint(Module_lock);
+  ClassLoaderData* boot_loader_data = ClassLoaderData::the_null_class_loader_data();
+  ModuleEntryTable* module_table = boot_loader_data->modules();
+
+  assert(module_table != NULL, "boot loader's ModuleEntryTable not defined");
+
+  if (jlrM_module.is_null()) {
+    fatal("Unable to finalize module definition for java.base");
+  }
+
+  // Set java.lang.reflect.Module, version and location for java.base
+  ModuleEntry* jb_module = javabase_module();
+  assert(jb_module != NULL, "java.base ModuleEntry not defined");
+  jb_module->set_jlrM_module(boot_loader_data->add_handle(jlrM_module));
+  jb_module->set_version(version);
+  jb_module->set_location(location);
+  // Store pointer to the ModuleEntry for java.base in the java.lang.reflect.Module object.
+  java_lang_reflect_Module::set_module_entry(jlrM_module(), jb_module);
+}
+
+void ModuleEntryTable::patch_javabase_entries(Handle jlrM_handle) {
+  if (jlrM_handle.is_null()) {
+    fatal("Unable to patch the module field of classes loaded prior to java.base's definition, invalid java.lang.reflect.Module");
+  }
+
+  // Do the fixups for the basic primitive types
+  java_lang_Class::set_module(Universe::int_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::float_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::double_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::byte_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::bool_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::char_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::long_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::short_mirror(), jlrM_handle());
+  java_lang_Class::set_module(Universe::void_mirror(), jlrM_handle());
+
+  // Do the fixups for classes that have already been created.
+  GrowableArray <Klass*>* list = java_lang_Class::fixup_modulefield_list();
+  int list_length = list->length();
+  for (int i = 0; i < list_length; i++) {
+    Klass* k = list->at(i);
+    assert(k->is_klass(), "List should only hold classes");
+    Thread* THREAD = Thread::current();
+    KlassHandle kh(THREAD, k);
+    java_lang_Class::fixup_modulefield(kh, jlrM_handle);
+  }
+
+  delete java_lang_Class::fixup_modulefield_list();
+  java_lang_Class::set_fixup_modulefield_list(NULL);
+}
+
+#ifndef PRODUCT
+void ModuleEntryTable::print() {
+  tty->print_cr("Module Entry Table (table_size=%d, entries=%d)",
+                table_size(), number_of_entries());
+  for (int i = 0; i < table_size(); i++) {
+    for (ModuleEntry* probe = bucket(i);
+                              probe != NULL;
+                              probe = probe->next()) {
+      probe->print();
+    }
+  }
+}
+
+void ModuleEntry::print() {
+  ResourceMark rm;
+  tty->print_cr("entry "PTR_FORMAT" name %s jlrM "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT,
+                p2i(this),
+                name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
+                p2i(jlrM_module()),
+                loader()->loader_name(),
+                version() != NULL ? version()->as_C_string() : "NULL",
+                location() != NULL ? location()->as_C_string() : "NULL",
+                BOOL_TO_STR(!can_read_all_unnamed()), p2i(next()));
+}
+#endif
+
+void ModuleEntryTable::verify() {
+  int element_count = 0;
+  for (int i = 0; i < table_size(); i++) {
+    for (ModuleEntry* probe = bucket(i);
+                              probe != NULL;
+                              probe = probe->next()) {
+      probe->verify();
+      element_count++;
+    }
+  }
+  guarantee(number_of_entries() == element_count,
+            "Verify of Module Entry Table failed");
+  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
+}
+
+void ModuleEntry::verify() {
+  guarantee(loader() != NULL, "A module entry must be associated with a loader.");
+}
+
+void ModuleEntry::set_version(Symbol* version) {
+  if (_version != NULL) {
+    _version->decrement_refcount();
+  }
+
+  _version = version;
+
+  if (version != NULL) {
+    version->increment_refcount();
+  }
+}
+
+void ModuleEntry::set_location(Symbol* location) {
+  if (_location != NULL) {
+    _location->decrement_refcount();
+  }
+
+  _location = location;
+
+  if (location != NULL) {
+    location->increment_refcount();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/moduleEntry.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_MODULEENTRY_HPP
+#define SHARE_VM_CLASSFILE_MODULEENTRY_HPP
+
+#include "classfile/classLoaderData.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "oops/symbol.hpp"
+#include "prims/jni.h"
+#include "runtime/mutexLocker.hpp"
+#include "trace/traceMacros.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.hpp"
+
+#define UNNAMED_MODULE "Unnamed Module"
+
+class ModuleClosure;
+
+// A ModuleEntry describes a module that has been defined by a call to JVM_DefineModule.
+// It contains:
+//   - Symbol* containing the module's name.
+//   - pointer to the java.lang.reflect.Module for this module.
+//   - ClassLoaderData*, class loader of this module.
+//   - a growable array containg other module entries that this module can read.
+//   - a flag indicating if this module can read all unnamed modules.
+//
+class ModuleEntry : public HashtableEntry<Symbol*, mtClass> {
+private:
+  jobject _jlrM;                       // java.lang.reflect.Module
+  jobject _pd;                         // java.security.ProtectionDomain, cached
+                                       // for shared classes from this module
+  ClassLoaderData* _loader;
+  GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
+  Symbol* _version;                    // module version number
+  Symbol* _location;                   // module location
+  bool _can_read_all_unnamed;
+  bool _has_default_read_edges;        // JVMTI redefine/retransform support
+  TRACE_DEFINE_TRACE_ID_FIELD;
+  enum {MODULE_READS_SIZE = 101};      // Initial size of list of modules that the module can read.
+
+public:
+  void init() {
+    _jlrM = NULL;
+    _loader = NULL;
+    _pd = NULL;
+    _reads = NULL;
+    _version = NULL;
+    _location = NULL;
+    _can_read_all_unnamed = false;
+    _has_default_read_edges = false;
+  }
+
+  Symbol*            name() const                   { return literal(); }
+  void               set_name(Symbol* n)            { set_literal(n); }
+
+  jobject            jlrM_module() const            { return _jlrM; }
+  void               set_jlrM_module(jobject j)     { _jlrM = j; }
+
+  // The shared ProtectionDomain reference is set once the VM loads a shared class
+  // originated from the current Module. The referenced ProtectionDomain object is
+  // created by the ClassLoader when loading a class (shared or non-shared) from the
+  // Module for the first time. This ProtectionDomain object is used for all
+  // classes from the Module loaded by the same ClassLoader.
+  Handle             shared_protection_domain();
+  void               set_shared_protection_domain(ClassLoaderData *loader_data,
+                                                  Handle pd);
+
+  ClassLoaderData*   loader() const                 { return _loader; }
+  void               set_loader(ClassLoaderData* l) { _loader = l; }
+
+  Symbol*            version() const                { return _version; }
+  void               set_version(Symbol* version);
+
+  Symbol*            location() const               { return _location; }
+  void               set_location(Symbol* location);
+
+  bool               can_read(ModuleEntry* m) const;
+  bool               has_reads() const;
+  void               add_read(ModuleEntry* m);
+
+  bool               is_named() const               { return (literal() != NULL); }
+
+  bool can_read_all_unnamed() const {
+    assert(is_named() || _can_read_all_unnamed == true,
+           "unnamed modules can always read all unnamed modules");
+    return _can_read_all_unnamed;
+  }
+
+  // Modules can only go from strict to loose.
+  void set_can_read_all_unnamed() { _can_read_all_unnamed = true; }
+
+  bool has_default_read_edges() const {
+    return _has_default_read_edges;
+  }
+
+  // Sets true and returns the previous value.
+  bool set_has_default_read_edges() {
+    MutexLocker ml(Module_lock);
+    bool prev = _has_default_read_edges;
+    _has_default_read_edges = true;
+    return prev;
+  }
+
+  ModuleEntry* next() const {
+    return (ModuleEntry*)HashtableEntry<Symbol*, mtClass>::next();
+  }
+  ModuleEntry** next_addr() {
+    return (ModuleEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
+  }
+
+  // iteration support for readability
+  void module_reads_do(ModuleClosure* const f);
+
+  TRACE_DEFINE_TRACE_ID_METHODS;
+
+  // Purge dead weak references out of reads list when any given class loader is unloaded.
+  void purge_reads();
+  void delete_reads();
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+// Iterator interface
+class ModuleClosure: public StackObj {
+ public:
+  virtual void do_module(ModuleEntry* const module) = 0;
+};
+
+
+// The ModuleEntryTable is a Hashtable containing a list of all modules defined
+// by a particular class loader.  Each module is represented as a ModuleEntry node.
+//
+// Each ModuleEntryTable contains a _javabase_module field which allows for the
+// creation of java.base's ModuleEntry very early in bootstrapping before the
+// corresponding JVM_DefineModule call for java.base occurs during module system
+// initialization.  Setting up java.base's ModuleEntry early enables classes,
+// loaded prior to the module system being initialized to be created with their
+// PackageEntry node's correctly pointing at java.base's ModuleEntry.  No class
+// outside of java.base is allowed to be loaded pre-module system initialization.
+//
+// The ModuleEntryTable's lookup is lock free.
+//
+class ModuleEntryTable : public Hashtable<Symbol*, mtClass> {
+  friend class VMStructs;
+public:
+  enum Constants {
+    _moduletable_entry_size  = 109 // number of entries in module entry table
+  };
+
+private:
+  static ModuleEntry* _javabase_module;
+  ModuleEntry* _unnamed_module;
+
+  ModuleEntry* new_entry(unsigned int hash, Handle jlrM_handle, Symbol* name, Symbol* version,
+                         Symbol* location, ClassLoaderData* class_loader);
+  void add_entry(int index, ModuleEntry* new_entry);
+
+public:
+  ModuleEntryTable(int table_size);
+  ~ModuleEntryTable();
+
+  int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
+
+  // Create module in loader's module entry table, if already exists then
+  // return null.  Assume Module_lock has been locked by caller.
+  ModuleEntry* locked_create_entry_or_null(Handle jlrM_handle,
+                                           Symbol* module_name,
+                                           Symbol* module_version,
+                                           Symbol* module_location,
+                                           ClassLoaderData* loader_data);
+
+  // Only lookup module within loader's module entry table.  The table read is lock-free.
+  ModuleEntry* lookup_only(Symbol* name);
+
+  ModuleEntry* bucket(int i) {
+    return (ModuleEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
+  }
+  ModuleEntry** bucket_addr(int i) {
+    return (ModuleEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
+  }
+
+  static unsigned int compute_hash(Symbol* name) { return ((name == NULL) ? 0 : (unsigned int)(name->identity_hash())); }
+  int index_for(Symbol* name) const              { return hash_to_index(compute_hash(name)); }
+
+  // purge dead weak references out of reads list
+  void purge_all_module_reads();
+
+  // Special handling for unnamed module, one per class loader's ModuleEntryTable
+  void create_unnamed_module(ClassLoaderData* loader_data);
+  ModuleEntry* unnamed_module() { return _unnamed_module; }
+
+  // Special handling for java.base
+  static ModuleEntry* javabase_module()                   { return _javabase_module; }
+  static void set_javabase_module(ModuleEntry* java_base) { _javabase_module = java_base; }
+  static bool javabase_defined()                          { return ((_javabase_module != NULL) &&
+                                                                    (_javabase_module->jlrM_module() != NULL)); }
+  static void finalize_javabase(Handle jlrM_module, Symbol* version, Symbol* location);
+  static void patch_javabase_entries(Handle jlrM_handle);
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+#endif // SHARE_VM_CLASSFILE_MODULEENTRY_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/modules.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,940 @@
+/*
+* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*
+*/
+
+#include "precompiled.hpp"
+#include "classfile/classFileParser.hpp"
+#include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
+#include "classfile/javaAssertions.hpp"
+#include "classfile/javaClasses.hpp"
+#include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
+#include "classfile/packageEntry.hpp"
+#include "classfile/stringTable.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/vmSymbols.hpp"
+#include "logging/log.hpp"
+#include "oops/instanceKlass.hpp"
+#include "oops/objArrayKlass.hpp"
+#include "oops/objArrayOop.inline.hpp"
+#include "runtime/arguments.hpp"
+#include "runtime/handles.inline.hpp"
+#include "runtime/javaCalls.hpp"
+#include "runtime/reflection.hpp"
+#include "utilities/utf8.hpp"
+
+static bool verify_module_name(char *module_name) {
+  if (module_name == NULL) return false;
+  int len = (int)strlen(module_name);
+  return (len > 0 && len <= Symbol::max_length() &&
+    UTF8::is_legal_utf8((unsigned char *)module_name, len, false) &&
+    ClassFileParser::verify_unqualified_name(module_name, len,
+    ClassFileParser::LegalModule));
+}
+
+bool Modules::verify_package_name(char *package_name) {
+  if (package_name == NULL) return false;
+  int len = (int)strlen(package_name);
+  return (len > 0 && len <= Symbol::max_length() &&
+    UTF8::is_legal_utf8((unsigned char *)package_name, len, false) &&
+    ClassFileParser::verify_unqualified_name(package_name, len,
+    ClassFileParser::LegalClass));
+}
+
+static char* get_module_name(oop module, TRAPS) {
+  oop name_oop = java_lang_reflect_Module::name(module);
+  if (name_oop == NULL) {
+    THROW_MSG_NULL(vmSymbols::java_lang_NullPointerException(), "Null module name");
+  }
+  char* module_name = java_lang_String::as_utf8_string(name_oop);
+  if (!verify_module_name(module_name)) {
+    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(),
+                   err_msg("Invalid module name: %s",
+                           module_name != NULL ? module_name : "NULL"));
+  }
+  return module_name;
+}
+
+static const char* get_module_version(jstring version) {
+  if (version == NULL) {
+    return NULL;
+  }
+  return java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(version));
+}
+
+static ModuleEntryTable* get_module_entry_table(Handle h_loader, TRAPS) {
+  // This code can be called during start-up, before the classLoader's classLoader data got
+  // created.  So, call register_loader() to make sure the classLoader data gets created.
+  ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
+  return loader_cld->modules();
+}
+
+static PackageEntryTable* get_package_entry_table(Handle h_loader, TRAPS) {
+  // This code can be called during start-up, before the classLoader's classLoader data got
+  // created.  So, call register_loader() to make sure the classLoader data gets created.
+  ClassLoaderData *loader_cld = SystemDictionary::register_loader(h_loader, CHECK_NULL);
+  return loader_cld->packages();
+}
+
+static ModuleEntry* get_module_entry(jobject module, TRAPS) {
+  Handle module_h(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_instance(module_h())) {
+    THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), "Bad module object");
+  }
+  return java_lang_reflect_Module::module_entry(module_h(), CHECK_NULL);
+}
+
+static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring package, TRAPS) {
+  ResourceMark rm;
+  if (package == NULL) return NULL;
+  const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  if (package_name == NULL) return NULL;
+  TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
+  PackageEntryTable* package_entry_table = module_entry->loader()->packages();
+  assert(package_entry_table != NULL, "Unexpected null package entry table");
+  return package_entry_table->lookup_only(pkg_symbol);
+}
+
+static PackageEntry* get_package_entry_by_name(Symbol* package,
+                                               Handle h_loader,
+                                               TRAPS) {
+  if (package != NULL) {
+    ResourceMark rm;
+    if (Modules::verify_package_name(package->as_C_string())) {
+      PackageEntryTable* const package_entry_table =
+        get_package_entry_table(h_loader, THREAD);
+      assert(package_entry_table != NULL, "Unexpected null package entry table");
+      return package_entry_table->lookup_only(package);
+    }
+  }
+  return NULL;
+}
+
+// Check if -Xpatch:<dirs> was specified.  If so, prepend each <dir>/module_name,
+// if it exists, to bootpath so boot loader can find the class files.  Also, if
+// using exploded modules, append <java.home>/modules/module_name, if it exists,
+// to bootpath so that its class files can be found by the boot loader.
+static void add_to_boot_loader_list(char *module_name, TRAPS) {
+  // java.base should be handled by argument parsing.
+  assert(strcmp(module_name, "java.base") != 0, "Unexpected java.base module name");
+  char file_sep = os::file_separator()[0];
+  size_t module_len = strlen(module_name);
+
+  // If -Xpatch is set then add <patch-dir>/module_name paths.
+  char** patch_dirs = Arguments::patch_dirs();
+  if (patch_dirs != NULL) {
+    int dir_count = Arguments::patch_dirs_count();
+    for (int x = 0; x < dir_count; x++) {
+      // Really shouldn't be NULL, but check can't hurt
+      if (patch_dirs[x] != NULL) {
+        size_t len = strlen(patch_dirs[x]);
+        if (len != 0) { // Ignore empty strings.
+          len = len + module_len + 2;
+          char* prefix_path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+          jio_snprintf(prefix_path, len, "%s%c%s", patch_dirs[x], file_sep, module_name);
+
+          // See if Xpatch module path exists.
+          struct stat st;
+          if ((os::stat(prefix_path, &st) != 0)) {
+            FREE_C_HEAP_ARRAY(char, prefix_path);
+          } else {
+            {
+              HandleMark hm;
+              Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
+              ObjectLocker ol(loader_lock, THREAD);
+              ClassLoader::prepend_to_list(prefix_path);
+            }
+            if (TraceClassLoading) tty->print_cr("[Opened -Xpatch %s]", prefix_path);
+          }
+        }
+      }
+    }
+  }
+
+  // If "modules" jimage does not exist then assume exploded form
+  // ${java.home}/modules/<module-name>
+  char* path = NULL;
+  if (!ClassLoader::has_jimage()) {
+    const char* home = Arguments::get_java_home();
+    size_t len = strlen(home) + module_len + 32;
+    path = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+    jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name);
+    struct stat st;
+    // See if exploded module path exists.
+    if ((os::stat(path, &st) != 0)) {
+      FREE_C_HEAP_ARRAY(char, path);
+      path = NULL;
+    }
+  }
+
+  if (path != NULL) {
+    HandleMark hm;
+    Handle loader_lock = Handle(THREAD, SystemDictionary::system_loader_lock());
+    ObjectLocker ol(loader_lock, THREAD);
+
+    if (TraceClassLoading) tty->print_cr("[Opened %s]", path);
+    ClassLoader::add_to_list(path);
+  }
+}
+
+bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
+  return get_package_entry_by_name(package, h_loader, THREAD) != NULL;
+}
+
+static void define_javabase_module(JNIEnv *env, jobject module, jstring version,
+                                   jstring location, jobjectArray packages) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+  ResourceMark rm(THREAD);
+
+  Handle jlrM_handle(THREAD, JNIHandles::resolve(module));
+
+  // Obtain java.base's module version
+  const char* module_version = get_module_version(version);
+  TempNewSymbol version_symbol;
+  if (module_version != NULL) {
+    version_symbol = SymbolTable::new_symbol(module_version, CHECK);
+  } else {
+    version_symbol = NULL;
+  }
+
+  // Obtain java.base's location
+  const char* module_location = NULL;
+  TempNewSymbol location_symbol = NULL;
+  if (location != NULL) {
+    module_location =
+      java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
+    if (module_location != NULL) {
+      location_symbol = SymbolTable::new_symbol(module_location, CHECK);
+    }
+  }
+
+  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
+  objArrayHandle packages_h(THREAD, packages_oop);
+  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
+
+  // Check that the list of packages has no duplicates and that the
+  // packages are syntactically ok.
+  GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
+  for (int x = 0; x < num_packages; x++) {
+    oop string_obj = packages_h->obj_at(x);
+
+    if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                "Bad package name for module: java.base");
+    }
+    char *package_name = java_lang_String::as_utf8_string(string_obj);
+    if (!Modules::verify_package_name(package_name)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Invalid package name: %s for module: java.base", package_name));
+    }
+    Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
+    // append_if_missing() returns FALSE if entry already exists.
+    if (!pkg_list->append_if_missing(pkg_symbol)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Duplicate package name: %s for module java.base",
+                        package_name));
+    }
+  }
+
+  // Validate java_base's loader is the boot loader.
+  oop loader = java_lang_reflect_Module::loader(jlrM_handle());
+  if (loader != NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader must be the boot class loader");
+  }
+  Handle h_loader = Handle(THREAD, loader);
+
+  // Ensure the boot loader's PackageEntryTable has been created
+  PackageEntryTable* package_table = get_package_entry_table(h_loader, CHECK);
+  assert(pkg_list->length() == 0 || package_table != NULL, "Bad package_table");
+
+  // Ensure java.base's ModuleEntry has been created
+  assert(ModuleEntryTable::javabase_module() != NULL, "No ModuleEntry for java.base");
+
+  {
+    MutexLocker m1(Module_lock, THREAD);
+
+    // Verify that all java.base packages created during bootstrapping are in
+    // pkg_list.  If any are not in pkg_list, than a non-java.base class was
+    // loaded erroneously pre java.base module definition.
+    package_table->verify_javabase_packages(pkg_list);
+
+    // loop through and add any new packages for java.base
+    PackageEntry* pkg;
+    for (int x = 0; x < pkg_list->length(); x++) {
+      // Some of java.base's packages were added early in bootstrapping, ignore duplicates.
+      if (package_table->lookup_only(pkg_list->at(x)) == NULL) {
+        pkg = package_table->locked_create_entry_or_null(pkg_list->at(x), ModuleEntryTable::javabase_module());
+        assert(pkg != NULL, "Unable to create a java.base package entry");
+      }
+      // Unable to have a GrowableArray of TempNewSymbol.  Must decrement the refcount of
+      // the Symbol* that was created above for each package. The refcount was incremented
+      // by SymbolTable::new_symbol and as well by the PackageEntry creation.
+      pkg_list->at(x)->decrement_refcount();
+    }
+
+    // Finish defining java.base's ModuleEntry
+    ModuleEntryTable::finalize_javabase(jlrM_handle, version_symbol, location_symbol);
+  }
+
+  log_debug(modules)("define_javabase_module(): Definition of module: java.base,"
+                     " version: %s, location: %s, package #: %d",
+                     module_version != NULL ? module_version : "NULL",
+                     module_location != NULL ? module_location : "NULL",
+                     pkg_list->length());
+
+  // packages defined to java.base
+  for (int x = 0; x < pkg_list->length(); x++) {
+    log_trace(modules)("define_javabase_module(): creation of package %s for module java.base",
+                       (pkg_list->at(x))->as_C_string());
+  }
+
+  // Patch any previously loaded classes' module field with java.base's jlr.Module.
+  ModuleEntryTable::patch_javabase_entries(jlrM_handle);
+}
+
+void Modules::define_module(JNIEnv *env, jobject module, jstring version,
+                            jstring location, jobjectArray packages) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
+  }
+  Handle jlrM_handle(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_subclass(jlrM_handle->klass())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is not a subclass of java.lang.reflect.Module");
+  }
+
+  char* module_name = get_module_name(jlrM_handle(), CHECK);
+  if (module_name == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Module name cannot be null");
+  }
+
+  // Special handling of java.base definition
+  if (strcmp(module_name, "java.base") == 0) {
+    define_javabase_module(env, module, version, location, packages);
+    return;
+  }
+
+  const char* module_version = get_module_version(version);
+
+  objArrayOop packages_oop = objArrayOop(JNIHandles::resolve(packages));
+  objArrayHandle packages_h(THREAD, packages_oop);
+  int num_packages = (packages_h == NULL ? 0 : packages_h->length());
+
+  // Check that the list of packages has no duplicates and that the
+  // packages are syntactically ok.
+  GrowableArray<Symbol*>* pkg_list = new GrowableArray<Symbol*>(num_packages);
+  for (int x = 0; x < num_packages; x++) {
+    oop string_obj = packages_h->obj_at(x);
+
+    if (string_obj == NULL || !string_obj->is_a(SystemDictionary::String_klass())) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Bad package name for module: %s", module_name));
+    }
+    char *package_name = java_lang_String::as_utf8_string(string_obj);
+    if (!verify_package_name(package_name)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Invalid package name: %s for module: %s",
+                        package_name, module_name));
+    }
+    Symbol* pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
+    // append_if_missing() returns FALSE if entry already exists.
+    if (!pkg_list->append_if_missing(pkg_symbol)) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                err_msg("Duplicate package name: %s for module %s",
+                        package_name, module_name));
+    }
+  }
+
+  oop loader = java_lang_reflect_Module::loader(jlrM_handle());
+  // Make sure loader is not the sun.reflect.DelegatingClassLoader.
+  if (loader != java_lang_ClassLoader::non_reflection_class_loader(loader)) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader is an invalid delegating class loader");
+  }
+  Handle h_loader = Handle(THREAD, loader);
+
+  // Check that loader is a subclass of java.lang.ClassLoader.
+  if (loader != NULL && !java_lang_ClassLoader::is_subclass(h_loader->klass())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader is not a subclass of java.lang.ClassLoader");
+  }
+
+  ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
+  assert(module_table != NULL, "module entry table shouldn't be null");
+
+  // Create symbol* entry for module name.
+  TempNewSymbol module_symbol = SymbolTable::new_symbol(module_name, CHECK);
+
+  int dupl_pkg_index = -1;
+  bool dupl_modules = false;
+
+  // Create symbol* entry for module version.
+  TempNewSymbol version_symbol;
+  if (module_version != NULL) {
+    version_symbol = SymbolTable::new_symbol(module_version, CHECK);
+  } else {
+    version_symbol = NULL;
+  }
+
+  // Create symbol* entry for module location.
+  const char* module_location = NULL;
+  TempNewSymbol location_symbol = NULL;
+  if (location != NULL) {
+    module_location =
+      java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(location));
+    if (module_location != NULL) {
+      location_symbol = SymbolTable::new_symbol(module_location, CHECK);
+    }
+  }
+
+  ClassLoaderData* loader_data = ClassLoaderData::class_loader_data_or_null(h_loader());
+  assert(loader_data != NULL, "class loader data shouldn't be null");
+
+  PackageEntryTable* package_table = NULL;
+  {
+    MutexLocker ml(Module_lock, THREAD);
+
+    if (num_packages > 0) {
+      package_table = get_package_entry_table(h_loader, CHECK);
+      assert(package_table != NULL, "Missing package_table");
+
+      // Check that none of the packages exist in the class loader's package table.
+      for (int x = 0; x < pkg_list->length(); x++) {
+        if (package_table->lookup_only(pkg_list->at(x)) != NULL) {
+          // This could be because the module was already defined.  If so,
+          // report that error instead of the package error.
+          if (module_table->lookup_only(module_symbol) != NULL) {
+            dupl_modules = true;
+          } else {
+            dupl_pkg_index = x;
+          }
+          break;
+        }
+      }
+    }  // if (num_packages > 0)...
+
+    // Add the module and its packages.
+    if (!dupl_modules && dupl_pkg_index == -1) {
+      // Create the entry for this module in the class loader's module entry table.
+
+      ModuleEntry* module_entry = module_table->locked_create_entry_or_null(jlrM_handle, module_symbol,
+                                    version_symbol, location_symbol, loader_data);
+
+      if (module_entry == NULL) {
+        dupl_modules = true;
+      } else {
+        // Add the packages.
+        assert(pkg_list->length() == 0 || package_table != NULL, "Bad package table");
+        PackageEntry* pkg;
+        for (int y = 0; y < pkg_list->length(); y++) {
+          pkg = package_table->locked_create_entry_or_null(pkg_list->at(y), module_entry);
+          assert(pkg != NULL, "Unable to create a module's package entry");
+
+          // Unable to have a GrowableArray of TempNewSymbol.  Must decrement the refcount of
+          // the Symbol* that was created above for each package. The refcount was incremented
+          // by SymbolTable::new_symbol and as well by the PackageEntry creation.
+          pkg_list->at(y)->decrement_refcount();
+        }
+
+        // Store pointer to ModuleEntry record in java.lang.reflect.Module object.
+        java_lang_reflect_Module::set_module_entry(jlrM_handle(), module_entry);
+      }
+    }
+  }  // Release the lock
+
+  // any errors ?
+  if (dupl_modules) {
+     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+               err_msg("Module %s is already defined", module_name));
+  }
+  if (dupl_pkg_index != -1) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s for module %s already exists for class loader",
+                      pkg_list->at(dupl_pkg_index)->as_C_string(), module_name));
+  }
+
+  if (log_is_enabled(Debug, modules)) {
+    outputStream* logst = LogHandle(modules)::debug_stream();
+    logst->print("define_module(): creation of module: %s, version: %s, location: %s, ",
+                 module_name, module_version != NULL ? module_version : "NULL",
+                 module_location != NULL ? module_location : "NULL");
+    loader_data->print_value_on(logst);
+    logst->print_cr(", package #: %d", pkg_list->length());
+    for (int y = 0; y < pkg_list->length(); y++) {
+      log_trace(modules)("define_module(): creation of package %s for module %s",
+                         (pkg_list->at(y))->as_C_string(), module_name);
+    }
+  }
+
+  if (loader == NULL && !Universe::is_module_initialized()) {
+    // Now that the module is defined, if it is in the bootloader, make sure that
+    // its classes can be found.  Check if -Xpatch:<path> was specified.  If
+    // so prepend <path>/module_name, if it exists, to bootpath.  Also, if using
+    // exploded modules, prepend <java.home>/modules/module_name, if it exists,
+    // to bootpath.
+    add_to_boot_loader_list(module_name, CHECK);
+  }
+}
+
+void Modules::set_bootloader_unnamed_module(JNIEnv *env, jobject module) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
+  }
+  Handle jlrM_handle(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_subclass(jlrM_handle->klass())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is not a subclass of java.lang.reflect.Module");
+  }
+
+  // Ensure that this is an unnamed module
+  oop name = java_lang_reflect_Module::name(jlrM_handle());
+  if (name != NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "boot loader's unnamed module's java.lang.reflect.Module has a name");
+  }
+
+  // Validate java_base's loader is the boot loader.
+  oop loader = java_lang_reflect_Module::loader(jlrM_handle());
+  if (loader != NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "Class loader must be the boot class loader");
+  }
+  Handle h_loader = Handle(THREAD, loader);
+
+  log_debug(modules)("set_bootloader_unnamed_module(): recording unnamed module for boot loader");
+
+  // Ensure the boot loader's PackageEntryTable has been created
+  ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK);
+
+  // Set java.lang.reflect.Module for the boot loader's unnamed module
+  ModuleEntry* unnamed_module = module_table->unnamed_module();
+  assert(unnamed_module != NULL, "boot loader's unnamed ModuleEntry not defined");
+  unnamed_module->set_jlrM_module(ClassLoaderData::the_null_class_loader_data()->add_handle(jlrM_handle));
+  // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module object.
+  java_lang_reflect_Module::set_module_entry(jlrM_handle(), unnamed_module);
+}
+
+void Modules::add_module_exports(JNIEnv *env, jobject from_module, jstring package, jobject to_module) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+
+  if (package == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "package is null");
+  }
+  if (from_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "from_module is null");
+  }
+  ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
+  if (from_module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "from_module cannot be found");
+  }
+
+  // All packages in unnamed are exported by default.
+  if (!from_module_entry->is_named()) return;
+
+  ModuleEntry* to_module_entry;
+  if (to_module == NULL) {
+    to_module_entry = NULL;  // It's an unqualified export.
+  } else {
+    to_module_entry = get_module_entry(to_module, CHECK);
+    if (to_module_entry == NULL) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                "to_module is invalid");
+    }
+  }
+
+  PackageEntry *package_entry = get_package_entry(from_module_entry, package, CHECK);
+  ResourceMark rm;
+  if (package_entry == NULL) {
+    const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s not found in from_module %s",
+                      package_name != NULL ? package_name : "",
+                      from_module_entry->name()->as_C_string()));
+  }
+  if (package_entry->module() != from_module_entry) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package: %s found in module %s, not in from_module: %s",
+                      package_entry->name()->as_C_string(),
+                      package_entry->module()->name()->as_C_string(),
+                      from_module_entry->name()->as_C_string()));
+  }
+
+  log_debug(modules)("add_module_exports(): package %s in module %s is exported to module %s",
+                     package_entry->name()->as_C_string(),
+                     from_module_entry->name()->as_C_string(),
+                     to_module_entry == NULL ? "NULL" :
+                      to_module_entry->is_named() ?
+                        to_module_entry->name()->as_C_string() : UNNAMED_MODULE);
+
+  // Do nothing if modules are the same or if package is already exported unqualifiedly.
+  if (from_module_entry != to_module_entry && !package_entry->is_unqual_exported()) {
+    package_entry->set_exported(to_module_entry);
+  }
+}
+
+
+void Modules::add_module_exports_qualified(JNIEnv *env, jobject from_module, jstring package, jobject to_module) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+  if (to_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "to_module is null");
+  }
+  add_module_exports(env, from_module, package, to_module);
+}
+
+void Modules::add_reads_module(JNIEnv *env, jobject from_module, jobject to_module) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+
+  if (from_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "from_module is null");
+  }
+
+  ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK);
+  if (from_module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "from_module is not valid");
+  }
+
+  ModuleEntry* to_module_entry;
+  if (to_module != NULL) {
+    to_module_entry = get_module_entry(to_module, CHECK);
+    if (to_module_entry == NULL) {
+      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+                "to_module is invalid");
+    }
+  } else {
+    to_module_entry = NULL;
+  }
+
+  ResourceMark rm;
+  log_debug(modules)("add_reads_module(): Adding read from module %s to module %s",
+                     from_module_entry->is_named() ?
+                     from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
+                      to_module_entry == NULL ? "all unnamed" :
+                        (to_module_entry->is_named() ?
+                          to_module_entry->name()->as_C_string() : UNNAMED_MODULE));
+
+  // if modules are the same or if from_module is unnamed then no need to add the read.
+  if (from_module_entry != to_module_entry && from_module_entry->is_named()) {
+    from_module_entry->add_read(to_module_entry);
+  }
+}
+
+jboolean Modules::can_read_module(JNIEnv *env, jobject asking_module, jobject target_module) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+
+  if (asking_module == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "asking_module is null", JNI_FALSE);
+  }
+
+  ModuleEntry* asking_module_entry = get_module_entry(asking_module, CHECK_false);
+  if (asking_module_entry == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "asking_module is invalid", JNI_FALSE);
+  }
+
+  // Calling can_read_all_unnamed() with NULL tests if a module is loose.
+  if (target_module == NULL) {
+    return asking_module_entry->can_read_all_unnamed();
+  }
+
+  ModuleEntry* target_module_entry = get_module_entry(target_module, CHECK_false);
+  if (target_module_entry == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "target_module is invalid", JNI_FALSE);
+  }
+
+  ResourceMark rm;
+  log_debug(modules)("can_read_module(): module %s trying to read module %s, allowed = %s",
+                     asking_module_entry->is_named() ?
+                       asking_module_entry->name()->as_C_string() : UNNAMED_MODULE,
+                     target_module_entry->is_named() ?
+                       target_module_entry->name()->as_C_string() : UNNAMED_MODULE,
+                     BOOL_TO_STR(asking_module_entry == target_module_entry ||
+                                 (asking_module_entry->can_read_all_unnamed() &&
+                                  !target_module_entry->is_named()) ||
+                                  asking_module_entry->can_read(target_module_entry)));
+
+  // Return true if:
+  // 1. the modules are the same, or
+  // 2. the asking_module is unnamed (because unnamed modules read everybody), or
+  // 3. the asking_module is loose and the target module is unnamed, or
+  // 4. if can_read() returns true.
+  if (asking_module_entry == target_module_entry ||
+      (asking_module_entry->can_read_all_unnamed() && !target_module_entry->is_named())) {
+    return true;
+  }
+  return asking_module_entry->can_read(target_module_entry);
+}
+
+jboolean Modules::is_exported_to_module(JNIEnv *env, jobject from_module, jstring package, jobject to_module) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+
+  if (package == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "package is null", JNI_FALSE);
+  }
+  if (from_module == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "from_module is null", JNI_FALSE);
+  }
+  ModuleEntry* from_module_entry = get_module_entry(from_module, CHECK_false);
+  if (from_module_entry == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "from_module is invalid", JNI_FALSE);
+  }
+  ModuleEntry* to_module_entry;
+  if (to_module == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "to_module is null", JNI_FALSE);
+  }
+  to_module_entry = get_module_entry(to_module, CHECK_false);
+  if (to_module_entry == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "to_module is invalid", JNI_FALSE);
+  }
+
+  PackageEntry *package_entry = get_package_entry(from_module_entry, package,
+                                                  CHECK_false);
+  ResourceMark rm;
+  if (package_entry == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               err_msg("Package not found in from_module: %s",
+                       from_module_entry->is_named() ?
+                         from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
+               JNI_FALSE);
+  }
+  if (package_entry->module() != from_module_entry) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               err_msg("Package: %s found in module %s, not in from_module: %s",
+                       package_entry->name()->as_C_string(),
+                       package_entry->module()->is_named() ?
+                         package_entry->module()->name()->as_C_string() : UNNAMED_MODULE,
+                       from_module_entry->is_named() ?
+                         from_module_entry->name()->as_C_string() : UNNAMED_MODULE),
+               JNI_FALSE);
+  }
+
+  log_debug(modules)("is_exported_to_module: package %s from module %s checking"
+                     " if exported to module %s, exported? = %s",
+                     package_entry->name()->as_C_string(),
+                     from_module_entry->is_named() ?
+                       from_module_entry->name()->as_C_string() : UNNAMED_MODULE,
+                     to_module_entry->is_named() ?
+                       to_module_entry->name()->as_C_string() : UNNAMED_MODULE,
+                     BOOL_TO_STR(!from_module_entry->is_named() ||
+                       package_entry->is_unqual_exported() ||
+                       from_module_entry == to_module_entry ||
+                       package_entry->is_qexported_to(to_module_entry)));
+
+  // Return true if:
+  // 1. from_module is unnamed because unnamed modules export all their packages (by default), or
+  // 2. if the package is unqualifiedly exported, or
+  // 3. if the modules are the same, or
+  // 4. if the package is exported to to_module
+  return (!from_module_entry->is_named() ||
+          package_entry->is_unqual_exported() ||
+          from_module_entry == to_module_entry ||
+          package_entry->is_qexported_to(to_module_entry));
+}
+
+// This method is called by JFR and JNI.
+jobject Modules::get_module(JNIEnv *env, jclass clazz) {
+  assert(ModuleEntryTable::javabase_defined(), "Attempt to call get_module before java.base is defined");
+
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+  if (clazz == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "class is null", JNI_FALSE);
+  }
+  oop mirror = JNIHandles::resolve_non_null(clazz);
+  if (mirror == NULL) {
+    log_debug(modules)("get_module(): no mirror, returning NULL");
+    return NULL;
+  }
+  if (!java_lang_Class::is_instance(mirror)) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "Invalid class", JNI_FALSE);
+  }
+
+  oop module = java_lang_Class::module(mirror);
+
+  assert(module != NULL, "java.lang.Class module field not set");
+  assert(java_lang_reflect_Module::is_subclass(module->klass()), "Module is not a java.lang.reflect.Module");
+
+  if (log_is_enabled(Debug, modules)) {
+    ResourceMark rm;
+    outputStream* logst = LogHandle(modules)::debug_stream();
+    Klass* klass = java_lang_Class::as_Klass(mirror);
+    oop module_name = java_lang_reflect_Module::name(module);
+    if (module_name != NULL) {
+      logst->print("get_module(): module ");
+      java_lang_String::print(module_name, tty);
+    } else {
+      logst->print("get_module(): Unamed Module");
+    }
+    if (klass != NULL) {
+      logst->print_cr(" for class %s", klass->external_name());
+    } else {
+      logst->print_cr(" for primitive class");
+    }
+  }
+
+  return JNIHandles::make_local(env, module);
+}
+
+// This method is called by JFR.
+jobject Modules::get_module(Symbol* package_name, Handle h_loader, TRAPS) {
+  const PackageEntry* const pkg_entry =
+    get_package_entry_by_name(package_name, h_loader, THREAD);
+  const ModuleEntry* const module_entry = (pkg_entry != NULL ? pkg_entry->module() : NULL);
+
+  if (module_entry != NULL &&
+      module_entry->jlrM_module() != NULL) {
+    return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->jlrM_module()));
+  }
+
+  return NULL;
+}
+
+void Modules::add_module_package(JNIEnv *env, jobject module, jstring package) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+  ResourceMark rm;
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "module is null");
+  }
+  if (package == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "package is null");
+  }
+  ModuleEntry* module_entry = get_module_entry(module, CHECK);
+  if (module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is invalid");
+  }
+  if (!module_entry->is_named()) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module cannot be an unnamed module");
+  }
+  char *package_name = java_lang_String::as_utf8_string(
+    JNIHandles::resolve_non_null(package));
+  if (package_name == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad package");
+  }
+  if (!verify_package_name(package_name)) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Invalid package name: %s", package_name));
+  }
+
+  log_debug(modules)("add_module_package(): Adding package %s to module %s",
+                     package_name, module_entry->name()->as_C_string());
+
+  TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
+  PackageEntryTable* package_table = module_entry->loader()->packages();
+  assert(package_table != NULL, "Missing package_table");
+
+  bool pkg_exists = false;
+  {
+    MutexLocker ml(Module_lock, THREAD);
+
+    // Check that the package does not exist in the class loader's package table.
+    if (!package_table->lookup_only(pkg_symbol)) {
+      PackageEntry* pkg = package_table->locked_create_entry_or_null(pkg_symbol, module_entry);
+      assert(pkg != NULL, "Unable to create a module's package entry");
+    } else {
+      pkg_exists = true;
+    }
+  }
+  if (pkg_exists) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s already exists for class loader", package_name));
+  }
+}
+
+// Export package in module to all unnamed modules.
+void Modules::add_module_exports_to_all_unnamed(JNIEnv *env, jobject module, jstring package) {
+  JavaThread *THREAD = JavaThread::thread_from_jni_environment(env);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "module is null");
+  }
+  if (package == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "package is null");
+  }
+  ModuleEntry* module_entry = get_module_entry(module, CHECK);
+  if (module_entry == NULL) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is invalid");
+  }
+  if (!module_entry->is_named()) {  // TBD: Should this be a no-op instead of an IAE ?
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module cannot be unnamed");
+  }
+
+  PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
+  ResourceMark rm;
+  if (package_entry == NULL) {
+    const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package %s not found in module %s",
+                      package_name != NULL ? package_name : "",
+                      module_entry->name()->as_C_string()));
+  }
+  if (package_entry->module() != module_entry) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              err_msg("Package: %s found in module %s, not in module: %s",
+                      package_entry->name()->as_C_string(),
+                      package_entry->module()->name()->as_C_string(),
+                      module_entry->name()->as_C_string()));
+  }
+
+  log_debug(modules)("add_module_exports_to_all_unnamed(): package %s in module"
+                     " %s is exported to all unnamed modules",
+                     package_entry->name()->as_C_string(),
+                     module_entry->name()->as_C_string());
+
+  // Mark package as exported to all unnamed modules, unless already
+  // unqualifiedly exported.
+  if (!package_entry->is_unqual_exported()) {
+    package_entry->set_is_exported_allUnnamed();
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/modules.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,143 @@
+/*
+* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* This code is free software; you can redistribute it and/or modify it
+* under the terms of the GNU General Public License version 2 only, as
+* published by the Free Software Foundation.
+*
+* This code is distributed in the hope that it will be useful, but WITHOUT
+* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+* FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+* version 2 for more details (a copy is included in the LICENSE file that
+* accompanied this code).
+*
+* You should have received a copy of the GNU General Public License version
+* 2 along with this work; if not, write to the Free Software Foundation,
+* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+*
+* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+* or visit www.oracle.com if you need additional information or have any
+* questions.
+*
+*/
+
+#ifndef SHARE_VM_CLASSFILE_MODULES_HPP
+#define SHARE_VM_CLASSFILE_MODULES_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/handles.hpp"
+
+class Symbol;
+
+class Modules : AllStatic {
+
+public:
+  // define_module defines a module containing the specified packages. It binds the
+  // module to its class loader by creating the ModuleEntry record in the
+  // ClassLoader's ModuleEntry table, and creates PackageEntry records in the class
+  // loader's PackageEntry table.  As in JVM_DefineClass the jstring format for all
+  // package names must use "/" and not "."
+  //
+  //  IllegalArgumentExceptions are thrown for the following :
+  // * Module's Class loader is not a subclass of java.lang.ClassLoader
+  // * Module's Class loader already has a module with that name
+  // * Module's Class loader has already defined types for any of the module's packages
+  // * Module_name is syntactically bad
+  // * Packages contains an illegal package name
+  // * Packages contains a duplicate package name
+  // * A package already exists in another module for this class loader
+  // * Module is an unnamed module
+  //  NullPointerExceptions are thrown if module is null.
+  static void define_module(JNIEnv *env, jobject module, jstring version,
+                             jstring location, jobjectArray packages);
+
+  // Provides the java.lang.reflect.Module for the unnamed module defined
+  // to the boot loader.
+  //
+  //  IllegalArgumentExceptions are thrown for the following :
+  //  * Module has a name
+  //  * Module is not a subclass of java.lang.reflect.Module
+  //  * Module's class loader is not the boot loader
+  //  NullPointerExceptions are thrown if module is null.
+  static void set_bootloader_unnamed_module(JNIEnv *env, jobject module);
+
+  // This either does a qualified export of package in module from_module to module
+  // to_module or, if to_module is null, does an unqualified export of package.
+  // The format for the package name must use "/' not ".".
+  //
+  // Error conditions causing IlegalArgumentException to be throw :
+  // * Module from_module does not exist
+  // * Module to_module is not null and does not exist
+  // * Package is not syntactically correct
+  // * Package is not defined for from_module's class loader
+  // * Package is not in module from_module.
+  static void add_module_exports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+
+  // This does a qualified export of package in module from_module to module
+  // to_module.  The format for the package name must use "/' not ".".
+  //
+  // Error conditions causing IlegalArgumentException to be throw :
+  // * Module from_module does not exist
+  // * Module to_module does not exist
+  // * Package is not syntactically correct
+  // * Package is not defined for from_module's class loader
+  // * Package is not in module from_module.
+  static void add_module_exports_qualified(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+
+  // add_reads_module adds module to_module to the list of modules that from_module
+  // can read.  If from_module is the same as to_module then this is a no-op.
+  // If to_module is null then from_module is marked as a loose module (meaning that
+  // from_module can read all current and future unnamed  modules).
+  // An IllegalArgumentException is thrown if from_module is null or either (non-null)
+  // module does not exist.
+  static void add_reads_module(JNIEnv *env, jobject from_module, jobject to_module);
+
+  // can_read_module returns TRUE if module asking_module can read module target_module,
+  // or if they are the same module, or if the asking_module is loose and target_module
+  // is null.
+  //
+  // Throws IllegalArgumentException if:
+  // * either asking_module or target_module is not a java.lang.reflect.Module
+  static jboolean can_read_module(JNIEnv *env, jobject asking_module, jobject target_module);
+
+  // If package is valid then this returns TRUE if module from_module exports
+  // package to module to_module, if from_module and to_module are the same
+  // module, or if package is exported without qualification.
+  //
+  // IllegalArgumentException is throw if:
+  // * Either to_module or from_module does not exist
+  // * package is syntactically incorrect
+  // * package is not in from_module
+  static jboolean is_exported_to_module(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+
+  // Return the java.lang.reflect.Module object for this class object.
+  static jobject get_module(JNIEnv *env, jclass clazz);
+
+  // If package is defined by loader, return the
+  // java.lang.reflect.Module object for the module in which the package is defined.
+  // Returns NULL if package is invalid or not defined by loader.
+  static jobject get_module(Symbol* package_name, Handle h_loader, TRAPS);
+
+  // This adds package to module.
+  // It throws IllegalArgumentException if:
+  // * Module is bad
+  // * Module is unnamed
+  // * Package is not syntactically correct
+  // * Package is already defined for module's class loader.
+  static void add_module_package(JNIEnv *env, jobject module, jstring package);
+
+  // Marks the specified package as exported to all unnamed modules.
+  // If either module or package is null then NullPointerException is thrown.
+  // If module or package is bad, or module is unnamed, or package is not in
+  // module then IllegalArgumentException is thrown.
+  static void add_module_exports_to_all_unnamed(JNIEnv *env, jobject module, jstring package);
+
+  // Return TRUE if package_name is syntactically valid, false otherwise.
+  static bool verify_package_name(char *package_name);
+
+  // Return TRUE iff package is defined by loader
+  static bool is_package_defined(Symbol* package_name, Handle h_loader, TRAPS);
+};
+
+#endif // SHARE_VM_CLASSFILE_MODULES_HPP
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/packageEntry.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/packageEntry.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/symbol.hpp"
+#include "runtime/handles.inline.hpp"
+#include "trace/traceMacros.hpp"
+#include "utilities/events.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.inline.hpp"
+
+// Return true if this package is exported to m.
+bool PackageEntry::is_qexported_to(ModuleEntry* m) const {
+  assert(m != NULL, "No module to lookup in this package's qualified exports list");
+  MutexLocker m1(Module_lock);
+  if (!_is_exported) {
+    return false;
+  } else if (_is_exported_allUnnamed && !m->is_named()) {
+    return true;
+  } else if (_qualified_exports == NULL) {
+    return false;
+  } else {
+    return _qualified_exports->contains(m);
+  }
+}
+
+// Add a module to the package's qualified export list.
+void PackageEntry::add_qexport(ModuleEntry* m) {
+  assert_locked_or_safepoint(Module_lock);
+  assert(_is_exported == true, "Adding a qualified export to a package that is not exported");
+  if (_qualified_exports == NULL) {
+    // Lazily create a package's qualified exports list.
+    // Initial size is small, do not anticipate export lists to be large.
+    _qualified_exports =
+      new (ResourceObj::C_HEAP, mtClass) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
+  }
+  _qualified_exports->append_if_missing(m);
+}
+
+// Set the package's exported state based on the value of the ModuleEntry.
+void PackageEntry::set_exported(ModuleEntry* m) {
+  MutexLocker m1(Module_lock);
+  if (is_unqual_exported()) {
+    // An exception could be thrown, but choose to simply ignore.
+    // Illegal to convert an unqualified exported package to be qualifiedly exported
+    return;
+  }
+
+  if (m == NULL) {
+    // NULL indicates the package is being unqualifiedly exported
+    if (_is_exported && _qualified_exports != NULL) {
+      // Legit to transition a package from being qualifiedly exported
+      // to unqualified.  Clean up the qualified lists at the next
+      // safepoint.
+      _exported_pending_delete = _qualified_exports;
+    }
+
+    // Mark package as unqualifiedly exported
+    set_unqual_exported();
+
+  } else {
+    // Add the exported module
+    _is_exported = true;
+    add_qexport(m);
+  }
+}
+
+// Remove dead module entries within the package's exported list.
+void PackageEntry::purge_qualified_exports() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  if (_qualified_exports != NULL) {
+    // Go backwards because this removes entries that are dead.
+    int len = _qualified_exports->length();
+    for (int idx = len - 1; idx >= 0; idx--) {
+      ModuleEntry* module_idx = _qualified_exports->at(idx);
+      ClassLoaderData* cld = module_idx->loader();
+      if (cld->is_unloading()) {
+        _qualified_exports->delete_at(idx);
+      }
+    }
+  }
+}
+
+void PackageEntry::delete_qualified_exports() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  if (_exported_pending_delete != NULL) {
+    // If a transition occurred from qualified to unqualified, the _qualified_exports
+    // field should have been NULL'ed out.
+    assert(_qualified_exports == NULL, "Package's exported pending delete, exported list should not be active");
+    delete _exported_pending_delete;
+  }
+
+  if (_qualified_exports != NULL) {
+    delete _qualified_exports;
+  }
+
+  _exported_pending_delete = NULL;
+  _qualified_exports = NULL;
+}
+
+PackageEntryTable::PackageEntryTable(int table_size)
+  : Hashtable<Symbol*, mtClass>(table_size, sizeof(PackageEntry))
+{
+}
+
+PackageEntryTable::~PackageEntryTable() {
+  assert_locked_or_safepoint(Module_lock);
+
+  // Walk through all buckets and all entries in each bucket,
+  // freeing each entry.
+  for (int i = 0; i < table_size(); ++i) {
+    for (PackageEntry* p = bucket(i); p != NULL;) {
+      PackageEntry* to_remove = p;
+      // read next before freeing.
+      p = p->next();
+
+      // Clean out the C heap allocated qualified exports list first before freeing the entry
+      to_remove->delete_qualified_exports();
+      to_remove->name()->decrement_refcount();
+
+      // Unlink from the Hashtable prior to freeing
+      unlink_entry(to_remove);
+      FREE_C_HEAP_ARRAY(char, to_remove);
+    }
+  }
+  assert(number_of_entries() == 0, "should have removed all entries");
+  assert(new_entry_free_list() == NULL, "entry present on PackageEntryTable's free list");
+  free_buckets();
+}
+
+PackageEntry* PackageEntryTable::new_entry(unsigned int hash, Symbol* name, ModuleEntry* module) {
+  assert_locked_or_safepoint(Module_lock);
+  PackageEntry* entry = (PackageEntry*) NEW_C_HEAP_ARRAY2(char, entry_size(), mtClass, CURRENT_PC);
+
+  // Initialize everything BasicHashtable would
+  entry->set_next(NULL);
+  entry->set_hash(hash);
+  entry->set_literal(name);
+
+  TRACE_INIT_PACKAGE_ID(entry);
+
+  // Initialize fields specific to a PackageEntry
+  entry->init();
+  entry->name()->increment_refcount();
+  if (!module->is_named()) {
+    // Set the exported state to true because all packages
+    // within the unnamed module are unqualifiedly exported
+    entry->set_exported(true);
+  }
+  entry->set_module(module);
+  return entry;
+}
+
+void PackageEntryTable::add_entry(int index, PackageEntry* new_entry) {
+  assert_locked_or_safepoint(Module_lock);
+  Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
+}
+
+// Create package in loader's package entry table and return the entry.
+// If entry already exists, return null.  Assume Module lock was taken by caller.
+PackageEntry* PackageEntryTable::locked_create_entry_or_null(Symbol* name, ModuleEntry* module) {
+  assert_locked_or_safepoint(Module_lock);
+  // Check if package already exists.  Return NULL if it does.
+  if (lookup_only(name) != NULL) {
+    return NULL;
+  } else {
+    PackageEntry* entry = new_entry(compute_hash(name), name, module);
+    add_entry(index_for(name), entry);
+    return entry;
+  }
+}
+
+PackageEntry* PackageEntryTable::lookup(Symbol* name, ModuleEntry* module) {
+  PackageEntry* p = lookup_only(name);
+  if (p != NULL) {
+    return p;
+  } else {
+    // If not found, add to table. Grab the PackageEntryTable lock first.
+    MutexLocker ml(Module_lock);
+
+    // Since look-up was done lock-free, we need to check if another thread beat
+    // us in the race to insert the package.
+    PackageEntry* test = lookup_only(name);
+    if (test != NULL) {
+      // A race occurred and another thread introduced the package.
+      return test;
+    } else {
+      assert(module != NULL, "module should never be null");
+      PackageEntry* entry = new_entry(compute_hash(name), name, module);
+      add_entry(index_for(name), entry);
+      return entry;
+    }
+  }
+}
+
+PackageEntry* PackageEntryTable::lookup_only(Symbol* name) {
+  int index = index_for(name);
+  for (PackageEntry* p = bucket(index); p != NULL; p = p->next()) {
+    if (p->name()->fast_compare(name) == 0) {
+      return p;
+    }
+  }
+  return NULL;
+}
+
+// Called when a define module for java.base is being processed.
+// Verify the packages loaded thus far are in java.base's package list.
+void PackageEntryTable::verify_javabase_packages(GrowableArray<Symbol*> *pkg_list) {
+  for (int i = 0; i < table_size(); i++) {
+    for (PackageEntry* entry = bucket(i);
+                       entry != NULL;
+                       entry = entry->next()) {
+      ModuleEntry* m = entry->module();
+      Symbol* module_name = (m == NULL ? NULL : m->name());
+      if (module_name != NULL &&
+          (module_name->fast_compare(vmSymbols::java_base()) == 0) &&
+          !pkg_list->contains(entry->name())) {
+        ResourceMark rm;
+        vm_exit_during_initialization("A non-java.base package was loaded prior to module system initialization", entry->name()->as_C_string());
+      }
+    }
+  }
+
+}
+
+// Remove dead entries from all packages' exported list
+void PackageEntryTable::purge_all_package_exports() {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+  for (int i = 0; i < table_size(); i++) {
+    for (PackageEntry* entry = bucket(i);
+                       entry != NULL;
+                       entry = entry->next()) {
+      if (entry->exported_pending_delete()) {
+        // exported list is pending deletion due to a transition
+        // from qualified to unqualified
+        entry->delete_qualified_exports();
+      } else if (entry->is_qual_exported()) {
+        entry->purge_qualified_exports();
+      }
+    }
+  }
+}
+
+#ifndef PRODUCT
+void PackageEntryTable::print() {
+  tty->print_cr("Package Entry Table (table_size=%d, entries=%d)",
+                table_size(), number_of_entries());
+  for (int i = 0; i < table_size(); i++) {
+    for (PackageEntry* probe = bucket(i);
+                       probe != NULL;
+                       probe = probe->next()) {
+      probe->print();
+    }
+  }
+}
+
+void PackageEntry::print() {
+  ResourceMark rm;
+  tty->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index "
+                INT32_FORMAT " is_exported %d is_exported_allUnnamed %d " "next "PTR_FORMAT,
+                p2i(this), name()->as_C_string(),
+                (module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
+                _classpath_index, _is_exported, _is_exported_allUnnamed, p2i(next()));
+}
+#endif
+
+void PackageEntryTable::verify() {
+  int element_count = 0;
+  for (int index = 0; index < table_size(); index++) {
+    for (PackageEntry* probe = bucket(index);
+                              probe != NULL;
+                              probe = probe->next()) {
+      probe->verify();
+      element_count++;
+    }
+  }
+  guarantee(number_of_entries() == element_count,
+            "Verify of Package Entry Table failed");
+  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
+}
+
+void PackageEntry::verify() {
+  guarantee(name() != NULL, "A package entry must have a corresponding symbol name.");
+}
+
+// iteration of qualified exports
+void PackageEntry::package_exports_do(ModuleClosure* const f) {
+  assert_locked_or_safepoint(Module_lock);
+  assert(f != NULL, "invariant");
+
+  if (is_qual_exported()) {
+    int qe_len = _qualified_exports->length();
+
+    for (int i = 0; i < qe_len; ++i) {
+      f->do_module(_qualified_exports->at(i));
+    }
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/packageEntry.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -0,0 +1,205 @@
+/*
+ * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
+#define SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
+
+#include "classfile/moduleEntry.hpp"
+#include "oops/symbol.hpp"
+#include "utilities/growableArray.hpp"
+#include "utilities/hashtable.hpp"
+
+// A PackageEntry basically represents a Java package.  It contains:
+//   - Symbol* containing the package's name.
+//   - ModuleEntry* for this package's containing module.
+//   - a flag indicating if package is exported, either qualifiedly or
+//     unqualifiedly.
+//   - a flag indicating if this package is exported to all unnamed modules.
+//   - a growable array containing other module entries that this
+//     package is exported to.
+//
+// Packages that are:
+//   - not exported:        _qualified_exports = NULL  && _is_exported is false
+//   - qualified exports:   (_qualified_exports != NULL || _is_exported_allUnnamed is true) && _is_exported is true
+//   - unqualified exports: (_qualified_exports = NULL && _is_exported_allUnnamed is false) && _is_exported is true
+//
+class PackageEntry : public HashtableEntry<Symbol*, mtClass> {
+private:
+  ModuleEntry* _module;
+  // Used to indicate for packages with classes loaded by the boot loader that
+  // a class in that package has been loaded.  And, for packages with classes
+  // loaded by the boot loader from -Xbootclasspath/a in an unnamed module, it
+  // indicates from which class path entry.
+  s2 _classpath_index;
+  bool _is_exported;
+  bool _is_exported_allUnnamed;
+  GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
+  GrowableArray<ModuleEntry*>* _qualified_exports;
+  TRACE_DEFINE_TRACE_ID_FIELD;
+
+  // Initial size of a package entry's list of qualified exports.
+  enum {QUAL_EXP_SIZE = 43};
+
+public:
+  void init() {
+    _module = NULL;
+    _classpath_index = -1;
+    _is_exported = false;
+    _is_exported_allUnnamed = false;
+    _exported_pending_delete = NULL;
+    _qualified_exports = NULL;
+  }
+
+  // package name
+  Symbol*            name() const               { return literal(); }
+  void               set_name(Symbol* n)        { set_literal(n); }
+
+  // the module containing the package definition
+  ModuleEntry*       module() const             { return _module; }
+  void               set_module(ModuleEntry* m) { _module = m; }
+
+  // package's export state
+  bool is_exported() const { return _is_exported; } // qualifiedly or unqualifiedly exported
+  bool is_qual_exported() const {
+    return (_is_exported && (_qualified_exports != NULL || _is_exported_allUnnamed));
+  }
+  bool is_unqual_exported() const {
+    return (_is_exported && (_qualified_exports == NULL && !_is_exported_allUnnamed));
+  }
+  void set_unqual_exported() {
+    _is_exported = true;
+    _is_exported_allUnnamed = false;
+    _qualified_exports = NULL;
+  }
+  bool exported_pending_delete() const     { return (_exported_pending_delete != NULL); }
+
+  void set_exported(bool e)                { _is_exported = e; }
+  void set_exported(ModuleEntry* m);
+
+  void set_is_exported_allUnnamed() {
+    if (!is_unqual_exported()) {
+     _is_exported_allUnnamed = true;
+     _is_exported = true;
+    }
+  }
+  bool is_exported_allUnnamed() const {
+    assert(_is_exported || !_is_exported_allUnnamed,
+           "is_allUnnamed set without is_exported being set");
+    return _is_exported_allUnnamed;
+  }
+
+  void set_classpath_index(s2 classpath_index) {
+    _classpath_index = classpath_index;
+  }
+  s2 classpath_index() const { return _classpath_index; }
+
+  bool has_loaded_class() const { return _classpath_index != -1; }
+
+  // returns true if the package is defined in the unnamed module
+  bool in_unnamed_module() const  { return !_module->is_named(); }
+
+  // returns true if the package specifies m as a qualified export
+  bool is_qexported_to(ModuleEntry* m) const;
+
+  // add the module to the package's qualified exports
+  void add_qexport(ModuleEntry* m);
+
+  PackageEntry* next() const {
+    return (PackageEntry*)HashtableEntry<Symbol*, mtClass>::next();
+  }
+
+  PackageEntry** next_addr() {
+    return (PackageEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
+  }
+
+  // iteration of qualified exports
+  void package_exports_do(ModuleClosure* const f);
+
+  TRACE_DEFINE_TRACE_ID_METHODS;
+
+  // Purge dead weak references out of exported list when any given class loader is unloaded.
+  void purge_qualified_exports();
+  void delete_qualified_exports();
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+// The PackageEntryTable is a Hashtable containing a list of all packages defined
+// by a particular class loader.  Each package is represented as a PackageEntry node.
+// The PackageEntryTable's lookup is lock free.
+//
+class PackageEntryTable : public Hashtable<Symbol*, mtClass> {
+  friend class VMStructs;
+public:
+  enum Constants {
+    _packagetable_entry_size = 1009  // number of entries in package entry table
+  };
+
+private:
+  PackageEntry* new_entry(unsigned int hash, Symbol* name, ModuleEntry* module);
+  void add_entry(int index, PackageEntry* new_entry);
+
+public:
+  PackageEntryTable(int table_size);
+  ~PackageEntryTable();
+
+  int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
+
+  // Create package in loader's package entry table and return the entry.
+  // If entry already exists, return null.  Assume Module lock was taken by caller.
+  PackageEntry* locked_create_entry_or_null(Symbol* name, ModuleEntry* module);
+
+  // lookup Package with loader's package entry table, if not found add
+  PackageEntry* lookup(Symbol* name, ModuleEntry* module);
+
+  // Only lookup Package within loader's package entry table.  The table read is lock-free.
+  PackageEntry* lookup_only(Symbol* Package);
+
+  PackageEntry* bucket(int i) {
+    return (PackageEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
+  }
+
+  PackageEntry** bucket_addr(int i) {
+    return (PackageEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
+  }
+
+  static unsigned int compute_hash(Symbol* name) {
+    return (unsigned int)(name->identity_hash());
+  }
+
+  int index_for(Symbol* name) const {
+    return hash_to_index(compute_hash(name));
+  }
+
+  void verify_javabase_packages(GrowableArray<Symbol*> *pkg_list);
+
+  // purge dead weak references out of exported list
+  void purge_all_package_exports();
+
+  void print() PRODUCT_RETURN;
+  void verify();
+};
+
+#endif // SHARE_VM_CLASSFILE_PACKAGEENTRY_HPP
--- a/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -111,7 +111,7 @@
   switch (type) {
   case BOOT:
     if (os::file_name_strcmp(path, Arguments::get_sysclasspath()) != 0) {
-      return fail("[BOOT classpath mismatch, actual: -Dsun.boot.class.path=", Arguments::get_sysclasspath());
+      return fail("[BOOT classpath mismatch, actual: -Djdk.boot.class.path.append=", Arguments::get_sysclasspath());
     }
     break;
   case NON_EXIST: // fall-through
--- a/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/sharedPathsMiscInfo.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -147,7 +147,7 @@
   virtual void print_path(outputStream* out, int type, const char* path) {
     switch (type) {
     case BOOT:
-      out->print("Expecting -Dsun.boot.class.path=%s", path);
+      out->print("Expecting BOOT path %s", path);
       break;
     case NON_EXIST:
       out->print("Expecting that %s does not exist", path);
--- a/src/share/vm/classfile/systemDictionary.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -32,6 +32,7 @@
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/klassFactory.hpp"
 #include "classfile/loaderConstraints.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/placeholders.hpp"
 #include "classfile/resolutionErrors.hpp"
 #include "classfile/stringTable.hpp"
@@ -51,6 +52,7 @@
 #include "oops/objArrayKlass.hpp"
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "prims/jvmtiEnvBase.hpp"
 #include "prims/methodHandles.hpp"
@@ -177,7 +179,7 @@
   if (class_loader.is_null()) {
     return false;
   }
-  return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
+  return (class_loader->klass()->name() == vmSymbols::jdk_internal_misc_ClassLoaders_ExtClassLoader());
 }
 
 // ----------------------------------------------------------------------------
@@ -1236,13 +1238,88 @@
   instanceKlassHandle ik (THREAD, find_shared_class(class_name));
   // Make sure we only return the boot class for the NULL classloader.
   if (ik.not_null() &&
-      SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
+      ik->is_shared_boot_class() && class_loader.is_null()) {
     Handle protection_domain;
     return load_shared_class(ik, class_loader, protection_domain, THREAD);
   }
   return instanceKlassHandle();
 }
 
+// Check if a shared class can be loaded by the specific classloader:
+//
+// NULL classloader:
+//   - Module class from "modules" jimage. ModuleEntry must be defined in the classloader.
+//   - Class from -Xbootclasspath/a. The class has no defined PackageEntry, or must
+//     be defined in an unnamed module.
+bool SystemDictionary::is_shared_class_visible(Symbol* class_name,
+                                               instanceKlassHandle ik,
+                                               Handle class_loader, TRAPS) {
+  int path_index = ik->shared_classpath_index();
+  SharedClassPathEntry* ent =
+            (SharedClassPathEntry*)FileMapInfo::shared_classpath(path_index);
+  if (!Universe::is_module_initialized()) {
+    assert(ent->is_jrt(),
+           "Loading non-bootstrap classes before the module system is initialized");
+    assert(class_loader.is_null(), "sanity");
+    return true;
+  }
+  // Get the pkg_entry from the classloader
+  TempNewSymbol pkg_name = NULL;
+  PackageEntry* pkg_entry = NULL;
+  ModuleEntry* mod_entry = NULL;
+  int length;
+  ClassLoaderData* loader_data = class_loader_data(class_loader);
+  const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+  if (pkg_string != NULL) {
+    pkg_name = SymbolTable::new_symbol((const char*)pkg_string,
+                                       length, CHECK_(false));
+    if (loader_data != NULL) {
+      pkg_entry = loader_data->packages()->lookup_only(pkg_name);
+    }
+    if (pkg_entry != NULL) {
+      mod_entry = pkg_entry->module();
+    }
+  }
+
+  if (class_loader.is_null()) {
+    // The NULL classloader can load archived class originated from the
+    // "modules" jimage and the -Xbootclasspath/a. For class from the
+    // "modules" jimage, the PackageEntry/ModuleEntry must be defined
+    // by the NULL classloader.
+    if (mod_entry != NULL) {
+      // PackageEntry/ModuleEntry is found in the classloader. Check if the
+      // ModuleEntry's location agrees with the archived class' origination.
+      if (ent->is_jrt() && mod_entry->location()->starts_with("jrt:")) {
+        return true; // Module class from the "module" jimage
+      }
+    }
+
+    // If the archived class is not from the "module" jimage, the class can be
+    // loaded by the NULL classloader if
+    //
+    // 1. the class is from the unamed package
+    // 2. or, the class is not from a module defined in the NULL classloader
+    // 3. or, the class is from an unamed module
+    if (!ent->is_jrt() && ik->is_shared_boot_class()) {
+      // the class is from the -Xbootclasspath/a
+      if (pkg_string == NULL ||
+          pkg_entry == NULL ||
+          pkg_entry->in_unnamed_module()) {
+        assert(mod_entry == NULL ||
+               mod_entry == loader_data->modules()->unnamed_module(),
+               "the unnamed module is not defined in the classloader");
+        return true;
+      }
+    }
+    return false;
+  } else {
+    bool res = SystemDictionaryShared::is_shared_class_visible_for_classloader(
+              ik, class_loader, pkg_string, pkg_name,
+              pkg_entry, mod_entry, CHECK_(false));
+    return res;
+  }
+}
+
 instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
                                                         Handle class_loader,
                                                         Handle protection_domain, TRAPS) {
@@ -1250,6 +1327,12 @@
     instanceKlassHandle nh = instanceKlassHandle(); // null Handle
     Symbol* class_name = ik->name();
 
+    bool visible = is_shared_class_visible(
+                            class_name, ik, class_loader, CHECK_(nh));
+    if (!visible) {
+      return nh;
+    }
+
     // Found the class, now load the superclass and interfaces.  If they
     // are shared, add them to the main system dictionary and reset
     // their hierarchy references (supers, subs, and interfaces).
@@ -1312,6 +1395,14 @@
       tty->print_cr("]");
     }
 
+    // For boot loader, ensure that GetSystemPackage knows that a class in this
+    // package was loaded.
+    if (class_loader.is_null()) {
+      int path_index = ik->shared_classpath_index();
+      ResourceMark rm;
+      ClassLoader::add_package(ik->name()->as_C_string(), path_index, THREAD);
+    }
+
     if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
       // Only dump the classes that can be stored into CDS archive
       if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
@@ -1330,7 +1421,69 @@
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
+
   if (class_loader.is_null()) {
+    int length;
+    TempNewSymbol pkg_name = NULL;
+    PackageEntry* pkg_entry = NULL;
+    bool search_only_bootloader_append = false;
+    ClassLoaderData *loader_data = class_loader_data(class_loader);
+
+    // Find the package in the boot loader's package entry table.
+    const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+    if (pkg_string != NULL) {
+      pkg_name = SymbolTable::new_symbol((const char*)pkg_string, length, CHECK_(nh));
+      pkg_entry = loader_data->packages()->lookup_only(pkg_name);
+    }
+
+    // Prior to attempting to load the class, enforce the boot loader's
+    // visibility boundaries.
+    if (!Universe::is_module_initialized()) {
+      // During bootstrapping, prior to module initialization, any
+      // class attempting to be loaded must be checked against the
+      // java.base packages in the boot loader's PackageEntryTable.
+      // No class outside of java.base is allowed to be loaded during
+      // this bootstrapping window.
+      if (!DumpSharedSpaces) {
+        if (pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
+          // Class is either in the unnamed package or in
+          // a named package within the unnamed module.  Either
+          // case is outside of java.base, do not attempt to
+          // load the class post java.base definition.  If
+          // java.base has not been defined, let the class load
+          // and its package will be checked later by
+          // ModuleEntryTable::verify_javabase_packages.
+          if (ModuleEntryTable::javabase_defined()) {
+            return nh;
+          }
+        } else {
+          // Check that the class' package is defined within java.base.
+          ModuleEntry* mod_entry = pkg_entry->module();
+          Symbol* mod_entry_name = mod_entry->name();
+          if (mod_entry_name->fast_compare(vmSymbols::java_base()) != 0) {
+            return nh;
+          }
+        }
+      }
+    } else {
+      assert(!DumpSharedSpaces, "Archive dumped after module system initialization");
+      // After the module system has been initialized, check if the class'
+      // package is in a module defined to the boot loader.
+      if (pkg_string == NULL || pkg_entry == NULL || pkg_entry->in_unnamed_module()) {
+        // Class is either in the unnamed package, in a named package
+        // within a module not defined to the boot loader or in a
+        // a named package within the unnamed module.  In all cases,
+        // limit visibility to search for the class only in the boot
+        // loader's append path.
+        search_only_bootloader_append = true;
+      }
+    }
+
+    // Prior to bootstrapping's module initialization, never load a class outside
+    // of the boot loader's module path
+    assert(Universe::is_module_initialized() || DumpSharedSpaces ||
+           !search_only_bootloader_append,
+           "Attempt to load a class outside of boot loader's module path");
 
     // Search the shared system dictionary for classes preloaded into the
     // shared spaces.
@@ -1345,7 +1498,7 @@
     if (k.is_null()) {
       // Use VM class loader
       PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time());
-      k = ClassLoader::load_class(class_name, CHECK_(nh));
+      k = ClassLoader::load_class(class_name, search_only_bootloader_append, CHECK_(nh));
     }
 
     // find_or_define_instance_class may return a different InstanceKlass
@@ -1670,7 +1823,7 @@
 }
 
 
-// Get the next class in the diictionary.
+// Get the next class in the dictionary.
 Klass* SystemDictionary::try_get_next_class() {
   return dictionary()->try_get_next_class();
 }
@@ -1941,6 +2094,11 @@
 
 void SystemDictionary::initialize_preloaded_classes(TRAPS) {
   assert(WK_KLASS(Object_klass) == NULL, "preloaded classes should only be initialized once");
+
+  // Create the ModuleEntry for java.base.  This call needs to be done here,
+  // after vmSymbols::initialize() is called but before any classes are pre-loaded.
+  ClassLoader::create_javabase();
+
   // Preload commonly used klasses
   WKID scan = FIRST_WKID;
   // first do Object, then String, Class
--- a/src/share/vm/classfile/systemDictionary.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -135,6 +135,7 @@
   do_klass(Properties_klass,                            java_util_Properties,                      Pre                 ) \
   do_klass(reflect_AccessibleObject_klass,              java_lang_reflect_AccessibleObject,        Pre                 ) \
   do_klass(reflect_Field_klass,                         java_lang_reflect_Field,                   Pre                 ) \
+  do_klass(reflect_Module_klass,                        java_lang_reflect_Module,                  Pre                 ) \
   do_klass(reflect_Parameter_klass,                     java_lang_reflect_Parameter,               Opt                 ) \
   do_klass(reflect_Method_klass,                        java_lang_reflect_Method,                  Pre                 ) \
   do_klass(reflect_Constructor_klass,                   java_lang_reflect_Constructor,             Pre                 ) \
@@ -167,15 +168,17 @@
   do_klass(StringBuffer_klass,                          java_lang_StringBuffer,                    Pre                 ) \
   do_klass(StringBuilder_klass,                         java_lang_StringBuilder,                   Pre                 ) \
   do_klass(internal_Unsafe_klass,                       jdk_internal_misc_Unsafe,                  Pre                 ) \
+  do_klass(module_Modules_klass,                        jdk_internal_module_Modules,               Pre                 ) \
                                                                                                                          \
   /* support for CDS */                                                                                                  \
   do_klass(ByteArrayInputStream_klass,                  java_io_ByteArrayInputStream,              Pre                 ) \
   do_klass(File_klass,                                  java_io_File,                              Pre                 ) \
-  do_klass(URLClassLoader_klass,                        java_net_URLClassLoader,                   Pre                 ) \
   do_klass(URL_klass,                                   java_net_URL,                              Pre                 ) \
   do_klass(Jar_Manifest_klass,                          java_util_jar_Manifest,                    Pre                 ) \
-  do_klass(sun_misc_Launcher_klass,                     sun_misc_Launcher,                         Pre                 ) \
+  do_klass(jdk_internal_misc_ClassLoaders_AppClassLoader_klass,  jdk_internal_misc_ClassLoaders_AppClassLoader,      Pre                 ) \
+  do_klass(jdk_internal_misc_ClassLoaders_ExtClassLoader_klass,  jdk_internal_misc_ClassLoaders_ExtClassLoader,      Pre                 ) \
   do_klass(CodeSource_klass,                            java_security_CodeSource,                  Pre                 ) \
+  do_klass(ParseUtil_klass,                             sun_net_www_ParseUtil,                     Pre                 ) \
                                                                                                                          \
   do_klass(StackTraceElement_klass,                     java_lang_StackTraceElement,               Opt                 ) \
                                                                                                                          \
@@ -639,6 +642,8 @@
   static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
                                                 Handle class_loader,
                                                 instanceKlassHandle k, TRAPS);
+  static bool is_shared_class_visible(Symbol* class_name, instanceKlassHandle ik,
+                                      Handle class_loader, TRAPS);
   static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
                                                Handle class_loader,
                                                Handle protection_domain,
--- a/src/share/vm/classfile/systemDictionaryShared.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/systemDictionaryShared.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -44,6 +44,16 @@
     oop class_loader = loader_data->class_loader();
     return (class_loader == NULL);
   }
+  static bool is_shared_class_visible_for_classloader(
+                                      instanceKlassHandle ik,
+                                      Handle class_loader,
+                                      const jbyte* pkg_string,
+                                      Symbol* pkg_name,
+                                      PackageEntry* pkg_entry,
+                                      ModuleEntry* mod_entry,
+                                      TRAPS) {
+    return false;
+  }
 
   static Klass* dump_time_resolve_super_or_fail(Symbol* child_name,
                                                 Symbol* class_name,
--- a/src/share/vm/classfile/vmSymbols.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -49,10 +49,12 @@
 // Mapping function names to values. New entries should be added below.
 
 #define VM_SYMBOLS_DO(template, do_alias)                                                         \
-  /* commonly used class names */                                                                 \
+  /* commonly used class, package, module names */                                                \
+  template(java_base,                                 "java.base")                                \
   template(java_lang_System,                          "java/lang/System")                         \
   template(java_lang_Object,                          "java/lang/Object")                         \
   template(java_lang_Class,                           "java/lang/Class")                          \
+  template(java_lang_Package,                         "java/lang/Package")                        \
   template(java_lang_String,                          "java/lang/String")                         \
   template(java_lang_StringLatin1,                    "java/lang/StringLatin1")                   \
   template(java_lang_StringUTF16,                     "java/lang/StringUTF16")                    \
@@ -87,6 +89,7 @@
   template(java_lang_reflect_Method,                  "java/lang/reflect/Method")                 \
   template(java_lang_reflect_Constructor,             "java/lang/reflect/Constructor")            \
   template(java_lang_reflect_Field,                   "java/lang/reflect/Field")                  \
+  template(java_lang_reflect_Module,                  "java/lang/reflect/Module")                 \
   template(java_lang_reflect_Parameter,               "java/lang/reflect/Parameter")              \
   template(java_lang_reflect_Array,                   "java/lang/reflect/Array")                  \
   template(java_lang_StringBuffer,                    "java/lang/StringBuffer")                   \
@@ -97,7 +100,6 @@
   template(java_security_CodeSource,                  "java/security/CodeSource")                 \
   template(java_security_ProtectionDomain,            "java/security/ProtectionDomain")           \
   template(java_security_SecureClassLoader,           "java/security/SecureClassLoader")          \
-  template(java_net_URLClassLoader,                   "java/net/URLClassLoader")                  \
   template(java_net_URL,                              "java/net/URL")                             \
   template(java_util_jar_Manifest,                    "java/util/jar/Manifest")                   \
   template(impliesCreateAccessControlContext_name,    "impliesCreateAccessControlContext")        \
@@ -116,17 +118,25 @@
   template(java_util_Hashtable,                       "java/util/Hashtable")                      \
   template(java_lang_Compiler,                        "java/lang/Compiler")                       \
   template(sun_misc_Signal,                           "sun/misc/Signal")                          \
-  template(sun_misc_Launcher,                         "sun/misc/Launcher")                        \
   template(java_lang_AssertionStatusDirectives,       "java/lang/AssertionStatusDirectives")      \
   template(getBootClassPathEntryForClass_name,        "getBootClassPathEntryForClass")            \
   template(sun_misc_PostVMInitHook,                   "sun/misc/PostVMInitHook")                  \
-  template(sun_misc_Launcher_ExtClassLoader,          "sun/misc/Launcher$ExtClassLoader")         \
+  template(sun_net_www_ParseUtil,                     "sun/net/www/ParseUtil")                    \
+                                                                                                  \
+  template(jdk_internal_misc_ClassLoaders_AppClassLoader,      "jdk/internal/misc/ClassLoaders$AppClassLoader")     \
+  template(jdk_internal_misc_ClassLoaders_ExtClassLoader,      "jdk/internal/misc/ClassLoaders$ExtClassLoader")     \
                                                                                                   \
   /* Java runtime version access */                                                               \
   template(sun_misc_Version,                          "sun/misc/Version")                         \
   template(java_runtime_name_name,                    "java_runtime_name")                        \
   template(java_runtime_version_name,                 "java_runtime_version")                     \
                                                                                                   \
+  /* system initialization */                                                                     \
+  template(initPhase1_name,                           "initPhase1")                               \
+  template(initPhase2_name,                           "initPhase2")                               \
+  template(initPhase3_name,                           "initPhase3")                               \
+  template(java_lang_reflect_module_init_signature,   "(Ljava/lang/ClassLoader;Ljava/lang/String;)V") \
+                                                                                                  \
   /* class file format tags */                                                                    \
   template(tag_source_file,                           "SourceFile")                               \
   template(tag_inner_classes,                         "InnerClasses")                             \
@@ -360,7 +370,6 @@
   template(run_finalization_name,                     "runFinalization")                          \
   template(run_finalizers_on_exit_name,               "runFinalizersOnExit")                      \
   template(dispatchUncaughtException_name,            "dispatchUncaughtException")                \
-  template(initializeSystemClass_name,                "initializeSystemClass")                    \
   template(loadClass_name,                            "loadClass")                                \
   template(loadClassInternal_name,                    "loadClassInternal")                        \
   template(get_name,                                  "get")                                      \
@@ -446,14 +455,20 @@
   template(signers_name,                              "signers_name")                             \
   template(loader_data_name,                          "loader_data")                              \
   template(vmdependencies_name,                       "vmdependencies")                           \
+  template(loader_name,                               "loader")                                   \
+  template(module_name,                               "module")                                   \
+  template(getModule_name,                            "getModule")                                \
   template(input_stream_void_signature,               "(Ljava/io/InputStream;)V")                 \
-  template(getFileURL_name,                           "getFileURL")                               \
-  template(getFileURL_signature,                      "(Ljava/io/File;)Ljava/net/URL;")           \
-  template(definePackageInternal_name,                "definePackageInternal")                    \
-  template(definePackageInternal_signature,           "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
+  template(definePackage_name,                        "definePackage")                            \
+  template(definePackage_signature,                   "(Ljava/lang/String;Ljava/lang/reflect/Module;)Ljava/lang/Package;") \
+  template(defineOrCheckPackage_name,                 "defineOrCheckPackage")                     \
+  template(defineOrCheckPackage_signature,            "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)Ljava/lang/Package;") \
+  template(fileToEncodedURL_name,                     "fileToEncodedURL")                         \
+  template(fileToEncodedURL_signature,                "(Ljava/io/File;)Ljava/net/URL;")           \
   template(getProtectionDomain_name,                  "getProtectionDomain")                      \
   template(getProtectionDomain_signature,             "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
   template(url_code_signer_array_void_signature,      "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
+  template(module_entry_name,                         "module_entry")                             \
                                                                                                   \
   /* non-intrinsic name/signature pairs: */                                                       \
   template(register_method_name,                      "register")                                 \
@@ -531,6 +546,7 @@
   template(void_class_signature,                      "()Ljava/lang/Class;")                                      \
   template(void_class_array_signature,                "()[Ljava/lang/Class;")                                     \
   template(void_string_signature,                     "()Ljava/lang/String;")                                     \
+  template(void_module_signature,                     "()Ljava/lang/reflect/Module;")                             \
   template(object_array_object_signature,             "([Ljava/lang/Object;)Ljava/lang/Object;")                  \
   template(object_object_array_object_signature,      "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
   template(exception_void_signature,                  "(Ljava/lang/Exception;)V")                                 \
@@ -550,6 +566,7 @@
   template(reference_signature,                       "Ljava/lang/ref/Reference;")                                \
   template(sun_misc_Cleaner_signature,                "Lsun/misc/Cleaner;")                                       \
   template(executable_signature,                      "Ljava/lang/reflect/Executable;")                           \
+  template(module_signature,                          "Ljava/lang/reflect/Module;")                               \
   template(concurrenthashmap_signature,               "Ljava/util/concurrent/ConcurrentHashMap;")                 \
   template(String_StringBuilder_signature,            "(Ljava/lang/String;)Ljava/lang/StringBuilder;")            \
   template(int_StringBuilder_signature,               "(I)Ljava/lang/StringBuilder;")                             \
@@ -574,6 +591,9 @@
   /* used to identify class loaders handling parallel class loading */                                            \
   template(parallelCapable_name,                      "parallelLockMap")                                          \
                                                                                                                   \
+  /* used to return a class loader's unnamed module */                                                            \
+  template(unnamedModule_name,                        "unnamedModule")                                            \
+                                                                                                                  \
   /* JVM monitoring and management support */                                                                     \
   template(java_lang_StackTraceElement_array,          "[Ljava/lang/StackTraceElement;")                          \
   template(java_lang_management_ThreadState,           "java/lang/management/ThreadState")                        \
@@ -632,7 +652,10 @@
   template(addThreadDumpForSynchronizers_signature,    "(Ljava/lang/management/ThreadInfo;[Ljava/lang/Object;)V")   \
                                                                                                                   \
   /* JVMTI/java.lang.instrument support and VM Attach mechanism */                                                \
+  template(jdk_internal_module_Modules,                "jdk/internal/module/Modules")                             \
   template(sun_misc_VMSupport,                         "sun/misc/VMSupport")                                      \
+  template(transformedByAgent_name,                    "transformedByAgent")                                      \
+  template(transformedByAgent_signature,               "(Ljava/lang/reflect/Module;)V")                           \
   template(appendToClassPathForInstrumentation_name,   "appendToClassPathForInstrumentation")                     \
   do_alias(appendToClassPathForInstrumentation_signature, string_void_signature)                                  \
   template(serializePropertiesToByteArray_name,        "serializePropertiesToByteArray")                          \
@@ -1063,11 +1086,6 @@
    do_name(     isCompileConstant_name,                          "isCompileConstant")                                   \
    do_alias(    isCompileConstant_signature,                      object_boolean_signature)                             \
                                                                                                                         \
-  do_class(sun_hotspot_WhiteBox,                                 "sun/hotspot/WhiteBox")                                \
-  do_intrinsic(_deoptimize,          sun_hotspot_WhiteBox,        deoptimize_name, deoptimize_signature, F_R)           \
-   do_name(     deoptimize_name,                                 "deoptimize")                                          \
-   do_alias(    deoptimize_signature,                             void_method_signature)                                \
-                                                                                                                        \
   /* unsafe memory references (there are a lot of them...) */                                                           \
   do_signature(getObject_signature,       "(Ljava/lang/Object;J)Ljava/lang/Object;")                                    \
   do_signature(putObject_signature,       "(Ljava/lang/Object;JLjava/lang/Object;)V")                                   \
--- a/src/share/vm/interpreter/bytecodeInterpreter.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -2258,10 +2258,8 @@
               // Decrement counter at checkcast.
               BI_PROFILE_SUBTYPECHECK_FAILED(objKlass);
               ResourceMark rm(THREAD);
-              const char* objName = objKlass->external_name();
-              const char* klassName = klassOf->external_name();
               char* message = SharedRuntime::generate_class_cast_message(
-                objName, klassName);
+                objKlass, klassOf);
               VM_JAVA_ERROR(vmSymbols::java_lang_ClassCastException(), message, note_classCheck_trap);
             }
             // Profile checkcast with null_seen and receiver.
--- a/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -384,7 +384,7 @@
 
   ResourceMark rm(thread);
   char* message = SharedRuntime::generate_class_cast_message(
-    thread, obj->klass()->external_name());
+    thread, obj->klass());
 
   if (ProfileTraps) {
     note_trap(thread, Deoptimization::Reason_class_check, CHECK);
--- a/src/share/vm/interpreter/linkResolver.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/interpreter/linkResolver.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -273,18 +273,25 @@
 // Klass resolution
 
 void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) {
-  if (!Reflection::verify_class_access(ref_klass(),
-                                       sel_klass(),
-                                       true)) {
+  Reflection::VerifyClassAccessResults vca_result =
+    Reflection::verify_class_access(ref_klass(), sel_klass(), true);
+  if (vca_result != Reflection::ACCESS_OK) {
     ResourceMark rm(THREAD);
-    Exceptions::fthrow(
-      THREAD_AND_LOCATION,
-      vmSymbols::java_lang_IllegalAccessError(),
-      "tried to access class %s from class %s",
-      sel_klass->external_name(),
-      ref_klass->external_name()
-    );
-    return;
+    char* msg = Reflection::verify_class_access_msg(ref_klass(), sel_klass(), vca_result);
+    if (msg == NULL) {
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_IllegalAccessError(),
+        "failed to access class %s from class %s",
+        sel_klass->external_name(),
+        ref_klass->external_name());
+    } else {
+      // Use module specific message returned by verify_class_access_msg().
+      Exceptions::fthrow(
+        THREAD_AND_LOCATION,
+        vmSymbols::java_lang_IllegalAccessError(),
+        "%s", msg);
+    }
   }
 }
 
--- a/src/share/vm/jvmci/jvmciEnv.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/jvmci/jvmciEnv.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -77,7 +77,9 @@
     resolved_klass = ObjArrayKlass::cast(resolved_klass())->bottom_klass();
   }
   if (resolved_klass->is_instance_klass()) {
-    return Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
+    Reflection::VerifyClassAccessResults result =
+      Reflection::verify_class_access(accessing_klass(), resolved_klass(), true);
+    return result == Reflection::ACCESS_OK;
   }
   return true;
 }
--- a/src/share/vm/logging/logTag.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/logging/logTag.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -58,6 +58,7 @@
   LOG_TAG(logging) \
   LOG_TAG(marking) \
   LOG_TAG(metaspace) \
+  LOG_TAG(modules) \
   LOG_TAG(monitorinflation) \
   LOG_TAG(phases) \
   LOG_TAG(plab) \
--- a/src/share/vm/memory/filemap.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/memory/filemap.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -228,12 +228,21 @@
           SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
         } else {
           struct stat st;
-          if ((os::stat(name, &st) == 0) && ((st.st_mode & S_IFDIR) == S_IFDIR)) {
-            if (!os::dir_is_empty(name)) {
-              ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
+          if (os::stat(name, &st) == 0) {
+            if (cpe->is_jrt()) {
+              // it's the "modules" jimage
+              ent->_timestamp = st.st_mtime;
+              ent->_filesize = st.st_size;
+            } else if ((st.st_mode & S_IFDIR) == S_IFDIR) {
+              if (!os::dir_is_empty(name)) {
+                ClassLoader::exit_with_path_failure(
+                  "Cannot have non-empty directory in archived classpaths", name);
+              }
+              ent->_filesize = -1;
             }
-            ent->_filesize = -1;
-          } else {
+          }
+          if (ent->_filesize == 0) {
+            // unknown
             ent->_filesize = -2;
           }
         }
@@ -286,7 +295,7 @@
         fail_continue("directory is not empty: %s", name);
         ok = false;
       }
-    } else if (ent->is_jar()) {
+    } else if (ent->is_jar_or_bootimage()) {
       if (ent->_timestamp != st.st_mtime ||
           ent->_filesize != st.st_size) {
         ok = false;
@@ -295,7 +304,7 @@
                         "Timestamp mismatch" :
                         "File size mismatch");
         } else {
-          fail_continue("A jar file is not the one used while building"
+          fail_continue("A jar/jimage file is not the one used while building"
                         " the shared archive file: %s", name);
         }
       }
@@ -877,6 +886,11 @@
     return false;
   }
 
+  if (Arguments::patch_dirs() != NULL) {
+    FileMapInfo::fail_continue("The shared archive file cannot be used with -Xpatch.");
+    return false;
+  }
+
   if (_version != current_version()) {
     FileMapInfo::fail_continue("The shared archive file is the wrong version.");
     return false;
--- a/src/share/vm/memory/filemap.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/memory/filemap.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -44,14 +44,20 @@
 class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
 public:
   const char *_name;
-  time_t _timestamp;          // jar timestamp,  0 if is directory or other
-  long   _filesize;           // jar file size, -1 if is directory, -2 if other
-  bool is_jar() {
+  time_t _timestamp;          // jar/jimage timestamp,  0 if is directory or other
+  long   _filesize;           // jar/jimage file size, -1 if is directory, -2 if other
+
+  // The _timestamp only gets set for jar files and "modules" jimage.
+  bool is_jar_or_bootimage() {
     return _timestamp != 0;
   }
   bool is_dir() {
     return _filesize == -1;
   }
+
+  bool is_jrt() {
+    return ClassLoader::is_jrt(_name);
+  }
 };
 
 class FileMapInfo : public CHeapObj<mtInternal> {
--- a/src/share/vm/memory/metaspaceShared.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/memory/metaspaceShared.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -602,14 +602,7 @@
   SystemDictionary::reverse();
   SystemDictionary::copy_buckets(&md_top, md_end);
 
-  ClassLoader::verify();
-  ClassLoader::copy_package_info_buckets(&md_top, md_end);
-  ClassLoader::verify();
-
   SystemDictionary::copy_table(&md_top, md_end);
-  ClassLoader::verify();
-  ClassLoader::copy_package_info_table(&md_top, md_end);
-  ClassLoader::verify();
 
   // Write the other data to the output array.
   WriteClosure wc(md_top, md_end);
@@ -733,6 +726,21 @@
   }
 }
 
+void MetaspaceShared::check_shared_class_loader_type(Klass* obj) {
+  InstanceKlass* ik = (InstanceKlass*)obj;
+  u2 loader_type = ik->loader_type();
+  if (loader_type == 0) {
+    tty->print_cr("Class loader type is not set for this class %s",
+      ik->name()->as_C_string());
+    exit(1);
+  }
+  if ((loader_type && !(loader_type & (loader_type - 1))) == 0) {
+    tty->print_cr("More than one loader type is set for this class %s",
+      ik->name()->as_C_string());
+    exit(1);
+  }
+}
+
 void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
   // We need to iterate because verification may cause additional classes
   // to be loaded.
@@ -764,6 +772,7 @@
 }
 
 void MetaspaceShared::prepare_for_dumping() {
+  Arguments::check_unsupported_dumping_properties();
   ClassLoader::initialize_shared_path();
   FileMapInfo::allocate_classpath_entry_table();
 }
@@ -842,6 +851,8 @@
     tty->print_cr("Shared spaces: preloaded %d classes", class_count);
   }
 
+  SystemDictionary::classes_do(check_shared_class_loader_type);
+
   // Rewrite and link classes
   tty->print_cr("Rewriting and linking classes ...");
 
@@ -899,7 +910,7 @@
   assert(DumpSharedSpaces, "should only be called during dumping");
   if (ik->init_state() < InstanceKlass::linked) {
     bool saved = BytecodeVerificationLocal;
-    if (!SharedClassUtil::is_shared_boot_class(ik)) {
+    if (!(ik->is_shared_boot_class())) {
       // The verification decision is based on BytecodeVerificationRemote
       // for non-system classes. Since we are using the NULL classloader
       // to load non-system classes during dumping, we need to temporarily
@@ -1087,36 +1098,14 @@
                                           number_of_entries);
   buffer += sharedDictionaryLen;
 
-  // Create the package info table using the bucket array at this spot in
-  // the misc data space.  Since the package info table is never
-  // modified, this region (of mapped pages) will be (effectively, if
-  // not explicitly) read-only.
-
-  int pkgInfoLen = *(intptr_t*)buffer;
-  buffer += sizeof(intptr_t);
-  number_of_entries = *(intptr_t*)buffer;
-  buffer += sizeof(intptr_t);
-  ClassLoader::create_package_info_table((HashtableBucket<mtClass>*)buffer, pkgInfoLen,
-                                         number_of_entries);
-  buffer += pkgInfoLen;
-  ClassLoader::verify();
-
   // The following data in the shared misc data region are the linked
   // list elements (HashtableEntry objects) for the shared dictionary
-  // and package info table.
+  // table.
 
   int len = *(intptr_t*)buffer;     // skip over shared dictionary entries
   buffer += sizeof(intptr_t);
   buffer += len;
 
-  len = *(intptr_t*)buffer;     // skip over package info table entries
-  buffer += sizeof(intptr_t);
-  buffer += len;
-
-  len = *(intptr_t*)buffer;     // skip over package info table char[] arrays.
-  buffer += sizeof(intptr_t);
-  buffer += len;
-
   intptr_t* array = (intptr_t*)buffer;
   ReadClosure rc(&array);
   serialize(&rc);
--- a/src/share/vm/memory/metaspaceShared.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/memory/metaspaceShared.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -208,6 +208,7 @@
   static bool try_link_class(InstanceKlass* ik, TRAPS);
   static void link_one_shared_class(Klass* obj, TRAPS);
   static void check_one_shared_class(Klass* obj);
+  static void check_shared_class_loader_type(Klass* obj);
   static void link_and_cleanup_shared_classes(TRAPS);
 
   static int count_class(const char* classlist_file);
--- a/src/share/vm/memory/universe.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/memory/universe.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -154,6 +154,7 @@
 
 int             Universe::_base_vtable_size = 0;
 bool            Universe::_bootstrapping = false;
+bool            Universe::_module_initialized = false;
 bool            Universe::_fully_initialized = false;
 
 size_t          Universe::_heap_capacity_at_last_gc;
@@ -664,7 +665,6 @@
   } else {
     SymbolTable::create_table();
     StringTable::create_table();
-    ClassLoader::create_package_info_table();
 
     if (DumpSharedSpaces) {
       MetaspaceShared::prepare_for_dumping();
@@ -883,6 +883,10 @@
   Universe::genesis(CATCH);
 }
 
+// Set after initialization of the module runtime, call_initModuleRuntime
+void universe_post_module_init() {
+  Universe::_module_initialized = true;
+}
 
 bool universe_post_init() {
   assert(!is_init_completed(), "Error: initialization not yet completed!");
--- a/src/share/vm/memory/universe.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/memory/universe.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -111,6 +111,7 @@
   friend jint  universe_init();
   friend void  universe2_init();
   friend bool  universe_post_init();
+  friend void  universe_post_module_init();
 
  private:
   // Known classes in the VM
@@ -205,6 +206,7 @@
 
   // Initialization
   static bool _bootstrapping;                         // true during genesis
+  static bool _module_initialized;                    // true after call_initPhase2 called
   static bool _fully_initialized;                     // true after universe_init and initialize_vtables called
 
   // the array of preallocated errors with backtraces
@@ -436,6 +438,7 @@
 
   // Testers
   static bool is_bootstrapping()                      { return _bootstrapping; }
+  static bool is_module_initialized()                 { return _module_initialized; }
   static bool is_fully_initialized()                  { return _fully_initialized; }
 
   static inline bool element_type_should_be_aligned(BasicType type);
--- a/src/share/vm/oops/arrayKlass.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/arrayKlass.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -93,17 +93,28 @@
     set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass());
     set_layout_helper(Klass::_lh_neutral_value);
     set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5)
-    TRACE_INIT_ID(this);
+    TRACE_INIT_KLASS_ID(this);
 }
 
 
 // Initialization of vtables and mirror object is done separatly from base_create_array_klass,
 // since a GC can happen. At this point all instance variables of the ArrayKlass must be setup.
-void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS) {
+void ArrayKlass::complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module_entry, TRAPS) {
   ResourceMark rm(THREAD);
   k->initialize_supers(super_klass(), CHECK);
   k->vtable()->initialize_vtable(false, CHECK);
-  java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(NULL), CHECK);
+
+  // During bootstrapping, before java.base is defined, the module_entry may not be present yet.
+  // These classes will be put on a fixup list and their module fields will be patched once
+  // java.base is defined.
+  assert((module_entry != NULL) || ((module_entry == NULL) && !ModuleEntryTable::javabase_defined()),
+         "module entry not available post java.base definition");
+  oop module = (oop)NULL;
+  if ((module_entry != NULL) && (module_entry->jlrM_module() != NULL)) {
+    module = JNIHandles::resolve(module_entry->jlrM_module());
+  }
+
+  java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(module), Handle(NULL), CHECK);
 }
 
 GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {
--- a/src/share/vm/oops/arrayKlass.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/arrayKlass.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -124,7 +124,7 @@
   void array_klasses_do(void f(Klass* k, TRAPS), TRAPS);
 
   // Return a handle.
-  static void     complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, TRAPS);
+  static void     complete_create_array_klass(ArrayKlass* k, KlassHandle super_klass, ModuleEntry* module, TRAPS);
 
 
   // jvm support
--- a/src/share/vm/oops/instanceKlass.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/instanceKlass.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1974,8 +1974,9 @@
 }
 
 void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+  instanceKlassHandle ik(THREAD, this);
+  ik->set_package(ik->name(), loader_data, CHECK);
   Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
-  instanceKlassHandle ik(THREAD, this);
 
   Array<Method*>* methods = ik->methods();
   int num_methods = methods->length();
@@ -2180,26 +2181,135 @@
   return dest;
 }
 
-// different verisons of is_same_class_package
+const jbyte* InstanceKlass::package_from_name(const Symbol* name, int& length) {
+  ResourceMark rm;
+  length = 0;
+  if (name == NULL) {
+    return NULL;
+  } else {
+    const jbyte* base_name = name->base();
+    const jbyte* last_slash = UTF8::strrchr(base_name, name->utf8_length(), '/');
+
+    if (last_slash == NULL) {
+      // No package name
+      return NULL;
+    } else {
+      // Skip over '['s
+      if (*base_name == '[') {
+        do {
+          base_name++;
+        } while (*base_name == '[');
+        if (*base_name != 'L') {
+          // Fully qualified class names should not contain a 'L'.
+          // Set length to -1 to indicate that the package name
+          // could not be obtained due to an error condition.
+          // In this situtation, is_same_class_package returns false.
+          length = -1;
+          return NULL;
+        }
+      }
+
+      // Found the package name, look it up in the symbol table.
+      length = last_slash - base_name;
+      assert(length > 0, "Bad length for package name");
+      return base_name;
+    }
+  }
+}
+
+ModuleEntry* InstanceKlass::module() const {
+  if (!in_unnamed_package()) {
+    return _package_entry->module();
+  }
+  const Klass* host = host_klass();
+  if (host == NULL) {
+    return class_loader_data()->modules()->unnamed_module();
+  }
+  return host->class_loader_data()->modules()->unnamed_module();
+}
+
+void InstanceKlass::set_package(Symbol* name, ClassLoaderData* loader, TRAPS) {
+  int length;
+  const jbyte* base_name = package_from_name(name, length);
+
+  if (base_name != NULL && loader != NULL) {
+    TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
+
+    // Find in class loader's package entry table.
+    _package_entry = loader->packages()->lookup_only(pkg_name);
+
+    // If the package name is not found in the loader's package
+    // entry table, it is an indication that the package has not
+    // been defined. Consider it defined within the unnamed module.
+    if (_package_entry == NULL) {
+      ResourceMark rm;
+
+      if (!ModuleEntryTable::javabase_defined()) {
+        // Before java.base is defined during bootstrapping, define all packages in
+        // the java.base module.  If a non-java.base package is erroneously placed
+        // in the java.base module it will be caught later when java.base
+        // is defined by ModuleEntryTable::verify_javabase_packages check.
+        assert(ModuleEntryTable::javabase_module() != NULL, "java.base module is NULL");
+        _package_entry = loader->packages()->lookup(pkg_name, ModuleEntryTable::javabase_module());
+      } else {
+        assert(loader->modules()->unnamed_module() != NULL, "unnamed module is NULL");
+        _package_entry = loader->packages()->lookup(pkg_name,
+                                                    loader->modules()->unnamed_module());
+      }
+
+      // A package should have been successfully created
+      assert(_package_entry != NULL, "Package entry for class %s not found, loader %s",
+             name->as_C_string(), loader->loader_name());
+    }
+
+    if (log_is_enabled(Debug, modules)) {
+      ResourceMark rm;
+      ModuleEntry* m = _package_entry->module();
+      log_trace(modules)("Setting package: class: %s, package: %s, loader: %s, module: %s",
+                         external_name(),
+                         pkg_name->as_C_string(),
+                         loader->loader_name(),
+                         (m->is_named() ? m->name()->as_C_string() : UNNAMED_MODULE));
+    }
+  } else {
+    ResourceMark rm;
+    log_trace(modules)("Setting package: class: %s, package: unnamed, loader: %s, module: %s",
+                       external_name(),
+                       (loader != NULL) ? loader->loader_name() : "NULL",
+                       UNNAMED_MODULE);
+  }
+}
+
+
+// different versions of is_same_class_package
+
 bool InstanceKlass::is_same_class_package(const Klass* class2) const {
-  const Klass* const class1 = (const Klass* const)this;
-  oop classloader1 = InstanceKlass::cast(class1)->class_loader();
-  const Symbol* const classname1 = class1->name();
-
+  oop classloader1 = this->class_loader();
+  PackageEntry* classpkg1 = this->package();
   if (class2->is_objArray_klass()) {
     class2 = ObjArrayKlass::cast(class2)->bottom_klass();
   }
+
   oop classloader2;
+  PackageEntry* classpkg2;
   if (class2->is_instance_klass()) {
-    classloader2 = InstanceKlass::cast(class2)->class_loader();
+    classloader2 = class2->class_loader();
+    classpkg2 = InstanceKlass::cast(class2)->package();
   } else {
     assert(class2->is_typeArray_klass(), "should be type array");
     classloader2 = NULL;
+    classpkg2 = NULL;
   }
-  const Symbol* classname2 = class2->name();
-
-  return InstanceKlass::is_same_class_package(classloader1, classname1,
-                                              classloader2, classname2);
+
+  // Same package is determined by comparing class loader
+  // and package entries. Both must be the same. This rule
+  // applies even to classes that are defined in the unnamed
+  // package, they still must have the same class loader.
+  if ((classloader1 == classloader2) && (classpkg1 == classpkg2)) {
+    return true;
+  }
+
+  return false;
 }
 
 bool InstanceKlass::is_same_class_package(oop other_class_loader,
@@ -2227,43 +2337,24 @@
     // The Symbol*'s are in UTF8 encoding. Since we only need to check explicitly
     // for ASCII characters ('/', 'L', '['), we can keep them in UTF8 encoding.
     // Otherwise, we just compare jbyte values between the strings.
-    const jbyte *name1 = class_name1->base();
-    const jbyte *name2 = class_name2->base();
-
-    const jbyte *last_slash1 = UTF8::strrchr(name1, class_name1->utf8_length(), '/');
-    const jbyte *last_slash2 = UTF8::strrchr(name2, class_name2->utf8_length(), '/');
-
-    if ((last_slash1 == NULL) || (last_slash2 == NULL)) {
+    int length1;
+    int length2;
+    const jbyte *name1 = package_from_name(class_name1, length1);
+    const jbyte *name2 = package_from_name(class_name2, length2);
+
+    if ((length1 < 0) || (length2 < 0)) {
+      // error occurred parsing package name.
+      return false;
+    }
+
+    if ((name1 == NULL) || (name2 == NULL)) {
       // One of the two doesn't have a package.  Only return true
       // if the other one also doesn't have a package.
-      return last_slash1 == last_slash2;
-    } else {
-      // Skip over '['s
-      if (*name1 == '[') {
-        do {
-          name1++;
-        } while (*name1 == '[');
-        if (*name1 != 'L') {
-          // Something is terribly wrong.  Shouldn't be here.
-          return false;
-        }
-      }
-      if (*name2 == '[') {
-        do {
-          name2++;
-        } while (*name2 == '[');
-        if (*name2 != 'L') {
-          // Something is terribly wrong.  Shouldn't be here.
-          return false;
-        }
-      }
-
-      // Check that package part is identical
-      int length1 = last_slash1 - name1;
-      int length2 = last_slash2 - name2;
-
-      return UTF8::equal(name1, length1, name2, length2);
+      return name1 == name2;
     }
+
+    // Check that package part is identical
+    return UTF8::equal(name1, length1, name2, length2);
   }
 }
 
@@ -2302,7 +2393,7 @@
   if (!class2->is_instance_klass())  return false;
 
   // must be in same package before we try anything else
-  if (!class1->is_same_class_package(class2->class_loader(), class2->name()))
+  if (!class1->is_same_class_package(InstanceKlass::cast(class2)))
     return false;
 
   // As long as there is an outer1.getEnclosingClass,
--- a/src/share/vm/oops/instanceKlass.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/instanceKlass.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -25,8 +25,11 @@
 #ifndef SHARE_VM_OOPS_INSTANCEKLASS_HPP
 #define SHARE_VM_OOPS_INSTANCEKLASS_HPP
 
+#include "classfile/classLoader.hpp"
 #include "classfile/classLoaderData.hpp"
+#include "classfile/packageEntry.hpp"
 #include "gc/shared/specialized_oop_closures.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "memory/referenceType.hpp"
 #include "oops/annotations.hpp"
 #include "oops/constMethod.hpp"
@@ -139,6 +142,8 @@
  protected:
   // Annotations for this class
   Annotations*    _annotations;
+  // Package this class is defined in
+  PackageEntry*   _package_entry;
   // Array classes holding elements of this class.
   Klass*          _array_klasses;
   // Constant pool for this class.
@@ -197,16 +202,22 @@
 
   // Start after _misc_kind field.
   enum {
-    _misc_rewritten                = 1 << 2, // methods rewritten.
-    _misc_has_nonstatic_fields     = 1 << 3, // for sizing with UseCompressedOops
-    _misc_should_verify_class      = 1 << 4, // allow caching of preverification
-    _misc_is_anonymous             = 1 << 5, // has embedded _host_klass field
-    _misc_is_contended             = 1 << 6, // marked with contended annotation
-    _misc_has_default_methods      = 1 << 7, // class/superclass/implemented interfaces has default methods
-    _misc_declares_default_methods = 1 << 8, // directly declares default methods (any access)
-    _misc_has_been_redefined       = 1 << 9, // class has been redefined
-    _misc_is_scratch_class         = 1 << 10 // class is the redefined scratch class
+    _misc_rewritten                = 1 << 2,  // methods rewritten.
+    _misc_has_nonstatic_fields     = 1 << 3,  // for sizing with UseCompressedOops
+    _misc_should_verify_class      = 1 << 4,  // allow caching of preverification
+    _misc_is_anonymous             = 1 << 5,  // has embedded _host_klass field
+    _misc_is_contended             = 1 << 6,  // marked with contended annotation
+    _misc_has_default_methods      = 1 << 7,  // class/superclass/implemented interfaces has default methods
+    _misc_declares_default_methods = 1 << 8,  // directly declares default methods (any access)
+    _misc_has_been_redefined       = 1 << 9,  // class has been redefined
+    _misc_is_scratch_class         = 1 << 10, // class is the redefined scratch class
+    _misc_is_shared_boot_class     = 1 << 11, // defining class loader is boot class loader
+    _misc_is_shared_ext_class      = 1 << 12, // defining class loader is ext class loader
+    _misc_is_shared_app_class      = 1 << 13  // defining class loader is app class loader
   };
+  u2 loader_type_bits() {
+    return _misc_is_shared_boot_class|_misc_is_shared_ext_class|_misc_is_shared_app_class;
+  }
   u2              _misc_flags;
   u2              _minor_version;        // minor version number of class file
   u2              _major_version;        // major version number of class file
@@ -290,6 +301,39 @@
   friend class SystemDictionary;
 
  public:
+  u2 loader_type() {
+    return _misc_flags & loader_type_bits();
+  }
+
+  bool is_shared_boot_class() const {
+    return (_misc_flags & _misc_is_shared_boot_class) != 0;
+  }
+  bool is_shared_ext_class() const {
+    return (_misc_flags & _misc_is_shared_ext_class) != 0;
+  }
+  bool is_shared_app_class() const {
+    return (_misc_flags & _misc_is_shared_app_class) != 0;
+  }
+
+  void set_class_loader_type(jshort loader_type) {
+    assert(( _misc_flags & loader_type_bits()) == 0,
+           "Should only be called once for each class.");
+    switch (loader_type) {
+    case ClassLoader::BOOT:
+      _misc_flags |= _misc_is_shared_boot_class;
+       break;
+    case ClassLoader::EXT:
+      _misc_flags |= _misc_is_shared_ext_class;
+      break;
+    case ClassLoader::APP:
+      _misc_flags |= _misc_is_shared_app_class;
+      break;
+    default:
+      ShouldNotReachHere();
+      break;
+    }
+  }
+
   bool has_nonstatic_fields() const        {
     return (_misc_flags & _misc_has_nonstatic_fields) != 0;
   }
@@ -399,6 +443,11 @@
   bool is_override(const methodHandle& super_method, Handle targetclassloader, Symbol* targetclassname, TRAPS);
 
   // package
+  PackageEntry* package() const     { return _package_entry; }
+  ModuleEntry* module() const;
+  bool in_unnamed_package() const   { return (_package_entry == NULL); }
+  void set_package(PackageEntry* p) { _package_entry = p; }
+  void set_package(Symbol* name, ClassLoaderData* loader, TRAPS);
   bool is_same_class_package(const Klass* class2) const;
   bool is_same_class_package(oop classloader2, const Symbol* classname2) const;
   static bool is_same_class_package(oop class_loader1,
@@ -843,7 +892,7 @@
 
   // support for stub routines
   static ByteSize init_state_offset()  { return in_ByteSize(offset_of(InstanceKlass, _init_state)); }
-  TRACE_DEFINE_OFFSET;
+  TRACE_DEFINE_KLASS_TRACE_ID_OFFSET;
   static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); }
 
   // subclass/subinterface checks
@@ -1042,6 +1091,7 @@
 
   // Naming
   const char* signature_name() const;
+  static const jbyte* package_from_name(const Symbol* name, int& length);
 
   // GC specific object visitors
   //
--- a/src/share/vm/oops/klass.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/klass.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -493,7 +493,7 @@
 }
 
 void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
-  TRACE_INIT_ID(this);
+  TRACE_INIT_KLASS_ID(this);
   // If an exception happened during CDS restore, some of these fields may already be
   // set.  We leave the class on the CLD list, even if incomplete so that we don't
   // modify the CLD list outside a safepoint.
@@ -511,7 +511,26 @@
   // gotten an OOM later but keep the mirror if it was created.
   if (java_mirror() == NULL) {
     Handle loader = loader_data->class_loader();
-    java_lang_Class::create_mirror(this, loader, protection_domain, CHECK);
+    ModuleEntry* module_entry = NULL;
+    Klass* k = this;
+    if (k->is_objArray_klass()) {
+      k = ObjArrayKlass::cast(k)->bottom_klass();
+    }
+    // Obtain klass' module.
+    if (k->is_instance_klass()) {
+      InstanceKlass* ik = (InstanceKlass*) k;
+      module_entry = ik->module();
+    } else {
+      module_entry = ModuleEntryTable::javabase_module();
+    }
+    // Obtain j.l.r.Module if available
+    oop jlrM_module = (oop)NULL;
+    if (module_entry != NULL &&
+        module_entry->jlrM_module() != NULL) {
+      jlrM_module = JNIHandles::resolve(module_entry->jlrM_module());
+    }
+    Handle jlrM_handle(THREAD, jlrM_module);
+    java_lang_Class::create_mirror(this, loader, jlrM_handle, protection_domain, CHECK);
   }
 }
 
--- a/src/share/vm/oops/klass.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/klass.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -137,7 +137,7 @@
   markOop  _prototype_header;   // Used when biased locking is both enabled and disabled for this type
   jint     _biased_lock_revocation_count;
 
-  TRACE_DEFINE_KLASS_TRACE_ID;
+  TRACE_DEFINE_TRACE_ID_FIELD;
 
   // Remembered sets support for the oops in the klasses.
   jbyte _modified_oops;             // Card Table Equivalent (YC/CMS support)
@@ -555,7 +555,7 @@
   jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; }
   void  set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; }
 
-  TRACE_DEFINE_KLASS_METHODS;
+  TRACE_DEFINE_TRACE_ID_METHODS;
 
   // garbage collection support
   void oops_do(OopClosure* cl);
--- a/src/share/vm/oops/objArrayKlass.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/objArrayKlass.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -135,8 +135,18 @@
   // GC walks these as strong roots.
   loader_data->add_class(oak);
 
+  // The array is defined in the module of its bottom class
+  Klass* bottom_klass = oak->bottom_klass();
+  ModuleEntry* module;
+  if (bottom_klass->is_instance_klass()) {
+    module = InstanceKlass::cast(bottom_klass)->module();
+  } else {
+    module = ModuleEntryTable::javabase_module();
+  }
+  assert(module != NULL, "No module entry for array");
+
   // Call complete_create_array_klass after all instance variables has been initialized.
-  ArrayKlass::complete_create_array_klass(oak, super_klass, CHECK_0);
+  ArrayKlass::complete_create_array_klass(oak, super_klass, module, CHECK_0);
 
   return oak;
 }
--- a/src/share/vm/oops/typeArrayKlass.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -70,7 +70,7 @@
   null_loader_data->add_class(ak);
 
   // Call complete_create_array_klass after all instance variables have been initialized.
-  complete_create_array_klass(ak, ak->super(), CHECK_NULL);
+  complete_create_array_klass(ak, ak->super(), ModuleEntryTable::javabase_module(), CHECK_NULL);
 
   return ak;
 }
--- a/src/share/vm/opto/library_call.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/opto/library_call.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -317,8 +317,6 @@
 
   bool inline_profileBoolean();
   bool inline_isCompileConstant();
-
-  bool inline_deoptimize();
 };
 
 //---------------------------make_vm_intrinsic----------------------------
@@ -760,9 +758,6 @@
   case vmIntrinsics::_hasNegatives:
     return inline_hasNegatives();
 
-  case vmIntrinsics::_deoptimize:
-    return inline_deoptimize();
-
   default:
     // If you get here, it may be that someone has added a new intrinsic
     // to the list in vmSymbols.hpp without implementing it here.
@@ -2943,7 +2938,7 @@
   Node* cls = null_check(argument(1), T_OBJECT);
   Node* kls = load_klass_from_mirror(cls, false, NULL, 0);
   kls = null_check(kls, T_OBJECT);
-  ByteSize offset = TRACE_ID_OFFSET;
+  ByteSize offset = TRACE_KLASS_TRACE_ID_OFFSET;
   Node* insp = basic_plus_adr(kls, in_bytes(offset));
   Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered);
   Node* bits = longcon(~0x03l); // ignore bit 0 & 1
@@ -6551,12 +6546,3 @@
   set_result(n->is_Con() ? intcon(1) : intcon(0));
   return true;
 }
-
-bool LibraryCallKit::inline_deoptimize() {
-  assert(WhiteBoxAPI, "");
-  PreserveReexecuteState preexecs(this);
-  jvms()->set_should_reexecute(false);
-  uncommon_trap(Deoptimization::Reason_intrinsic,
-                Deoptimization::Action_none);
-  return true;
-}
--- a/src/share/vm/precompiled/precompiled.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/precompiled/precompiled.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -58,6 +58,9 @@
 # include "classfile/classFileStream.hpp"
 # include "classfile/classLoader.hpp"
 # include "classfile/javaClasses.hpp"
+# include "classfile/moduleEntry.hpp"
+# include "classfile/modules.hpp"
+# include "classfile/packageEntry.hpp"
 # include "classfile/symbolTable.hpp"
 # include "classfile/systemDictionary.hpp"
 # include "classfile/vmSymbols.hpp"
--- a/src/share/vm/prims/jni.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jni.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -29,6 +29,7 @@
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -3452,6 +3453,19 @@
   return JNI_OK;
 JNI_END
 
+
+DT_RETURN_MARK_DECL(GetModule, jobject, HOTSPOT_JNI_GETMODULE_RETURN(_ret_ref));
+
+JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
+  JNIWrapper("GetModule");
+  HOTSPOT_JNI_GETMODULE_ENTRY(env, clazz);
+  jobject res;
+  DT_RETURN_MARK(GetModule, jobject, (const jobject&)res);
+  res = Modules::get_module(env, clazz);
+  return res;
+JNI_END
+
+
 // Structure containing all jni functions
 struct JNINativeInterface_ jni_NativeInterface = {
     NULL,
@@ -3731,7 +3745,11 @@
 
     // New 1_6 features
 
-    jni_GetObjectRefType
+    jni_GetObjectRefType,
+
+    // Module features
+
+    jni_GetModule
 };
 
 
--- a/src/share/vm/prims/jni.h	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jni.h	Thu Feb 18 11:41:21 2016 -0800
@@ -765,6 +765,11 @@
 
     jobjectRefType (JNICALL *GetObjectRefType)
         (JNIEnv* env, jobject obj);
+
+    /* Module Features */
+
+    jobject (JNICALL *GetModule)
+       (JNIEnv* env, jclass clazz);
 };
 
 /*
@@ -1857,6 +1862,12 @@
         return functions->GetObjectRefType(this, obj);
     }
 
+    /* Module Features */
+
+    jobject GetModule(jclass clazz) {
+        return functions->GetModule(this, clazz);
+    }
+
 #endif /* __cplusplus */
 };
 
--- a/src/share/vm/prims/jniCheck.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jniCheck.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1989,7 +1989,17 @@
     return result;
 JNI_END
 
-
+JNI_ENTRY_CHECKED(jobject,
+  checked_jni_GetModule(JNIEnv *env,
+                        jclass clazz))
+    functionEnter(thr);
+    IN_VM(
+        jniCheck::validate_class(thr, clazz, false);
+    )
+    jobject result = UNCHECKED()->GetModule(env,clazz);
+    functionExit(thr);
+    return result;
+JNI_END
 
 /*
  * Structure containing all checked jni functions
@@ -2272,7 +2282,11 @@
 
     // New 1.6 Features
 
-    checked_jni_GetObjectRefType
+    checked_jni_GetObjectRefType,
+
+    // Module Features
+
+    checked_jni_GetModule
 };
 
 
--- a/src/share/vm/prims/jvm.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvm.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -25,8 +25,12 @@
 #include "precompiled.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/classLoaderData.inline.hpp"
 #include "classfile/javaAssertions.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/modules.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -1047,6 +1051,53 @@
             (jclass) JNIHandles::make_local(env, k->java_mirror());
 JVM_END
 
+// Module support //////////////////////////////////////////////////////////////////////////////
+
+JVM_ENTRY(void, JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
+                                 jobjectArray packages))
+  JVMWrapper("JVM_DefineModule");
+  Modules::define_module(env, module, version, location, packages);
+JVM_END
+
+JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
+  JVMWrapper("JVM_SetBootLoaderUnnamedModule");
+  Modules::set_bootloader_unnamed_module(env, module);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
+  JVMWrapper("JVM_AddModuleExports");
+  Modules::add_module_exports_qualified(env, from_module, package, to_module);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
+  JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
+  Modules::add_module_exports_to_all_unnamed(env, from_module, package);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
+  JVMWrapper("JVM_AddModuleExportsToAll");
+  Modules::add_module_exports(env, from_module, package, NULL);
+JVM_END
+
+JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module))
+  JVMWrapper("JVM_AddReadsModule");
+  Modules::add_reads_module(env, from_module, source_module);
+JVM_END
+
+JVM_ENTRY(jboolean, JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module))
+  JVMWrapper("JVM_CanReadModule");
+  return Modules::can_read_module(env, asking_module, source_module);
+JVM_END
+
+JVM_ENTRY(jboolean, JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module))
+  JVMWrapper("JVM_IsExportedToModule");
+  return Modules::is_exported_to_module(env, from_module, package, to_module);
+JVM_END
+
+JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
+  JVMWrapper("JVM_AddModulePackage");
+  Modules::add_module_package(env, module, package);
+JVM_END
 
 // Reflection support //////////////////////////////////////////////////////////////////////////////
 
--- a/src/share/vm/prims/jvm.h	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvm.h	Thu Feb 18 11:41:21 2016 -0800
@@ -417,6 +417,38 @@
                           const char *source);
 
 /*
+ * Module support funcions
+ */
+
+JNIEXPORT void JNICALL
+JVM_DefineModule(JNIEnv *env, jobject module, jstring version, jstring location,
+                 jobjectArray packages);
+
+JNIEXPORT void JNICALL
+JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExports(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package);
+
+JNIEXPORT void JNICALL
+JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package);
+
+JNIEXPORT void JNICALL
+JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module);
+
+JNIEXPORT jboolean JNICALL
+JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module);
+
+JNIEXPORT jboolean JNICALL
+JVM_IsExportedToModule(JNIEnv *env, jobject from_module, jstring package, jobject to_module);
+
+JNIEXPORT void JNICALL
+JVM_AddModulePackage(JNIEnv* env,  jobject module, jstring package);
+
+/*
  * Reflection support functions
  */
 
@@ -920,6 +952,7 @@
 #define JVM_ACC_SYNTHETIC     0x1000  /* compiler-generated class, method or field */
 #define JVM_ACC_ANNOTATION    0x2000  /* annotation type */
 #define JVM_ACC_ENUM          0x4000  /* field is declared as element of enum */
+#define JVM_ACC_MODULE        0x8000  /* module-info class file */
 
 #define JVM_ACC_PUBLIC_BIT        0
 #define JVM_ACC_PRIVATE_BIT       1
--- a/src/share/vm/prims/jvmti.xml	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmti.xml	Thu Feb 18 11:41:21 2016 -0800
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="ISO-8859-1"?>
 <?xml-stylesheet type="text/xsl" href="jvmti.xsl"?>
 <!--
- Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -356,9 +356,9 @@
  ]>
 
 <specification label="JVM(TM) Tool Interface"
-        majorversion="1"
-        minorversion="2"
-        microversion="3">
+        majorversion="9"
+        minorversion="0"
+        microversion="0">
   <title subtitle="Version">
     <tm>JVM</tm> Tool Interface
   </title>
@@ -1880,10 +1880,6 @@
 	  <outptr><struct>jvmtiThreadInfo</struct></outptr>
 	  <description>
 	    On return, filled with information describing the specified thread.
-	    <p/>
-	    For JDK 1.1 implementations that don't
-	    recognize context class loaders, 
-	    the <code>context_class_loader</code> field will be NULL.
 	  </description>
 	</param>
       </parameters>
@@ -6460,6 +6456,43 @@
     </function>
   </category>
 
+  <category id="module" label="Module">
+
+    <intro>
+    </intro>
+
+    <function id="GetAllModules" num="3" since="9">
+      <synopsis>Get All Modules</synopsis>
+      <description>
+	Return an array of all modules loaded in the virtual machine.
+	The number of modules in the array is returned via
+	<code>module_count_ptr</code>, and the array itself via
+	<code>modules_ptr</code>.
+	<p/>
+      </description>
+      <origin>new</origin>
+      <capabilities>
+      </capabilities>
+      <parameters>
+	<param id="module_count_ptr">
+	  <outptr><jint/></outptr>
+	  <description>
+	    On return, points to the number of returned modules.
+	  </description>
+	</param>
+	<param id="modules_ptr">
+	  <allocbuf outcount="module_count_ptr"><jobject/></allocbuf>
+	    <description>
+	      On return, points to an array of references, one
+              for each module.
+	    </description>
+	</param>
+      </parameters>
+      <errors>
+      </errors>
+    </function>
+  </category>
+
   <category id="class" label="Class">
 
     <intro>
@@ -6508,9 +6541,6 @@
 	either by defining it directly or by delegation to another class loader.
 	See <vmspec chapter="5.3"/>.
 	<p/>
-	For JDK version 1.1 implementations that don't
-	recognize the distinction between initiating and defining class loaders,
-	this function should return all classes loaded in the virtual machine.
 	The number of classes in the array is returned via
 	<code>class_count_ptr</code>, and the array itself via
 	<code>classes_ptr</code>.
@@ -12351,7 +12381,7 @@
     </parameters>
   </event>
 
-  <event label="Class File Load Hook" phase="any"
+  <event label="Class File Load Hook" phase="start"
 	 id="ClassFileLoadHook" const="JVMTI_EVENT_CLASS_FILE_LOAD_HOOK" num="54">
     <description>
       This event is sent when the VM obtains class file data,
@@ -12367,9 +12397,9 @@
       <internallink id="bci">bytecode instrumentation</internallink>
       for usage information.
       <p/>
-    This event may be sent before the VM is initialized (the primordial 
-    <functionlink id="GetPhase">phase</functionlink>). During this time
-    no VM resources should be created.  Some classes might not be compatible
+    This event may be sent before the VM is initialized (the start 
+    <functionlink id="GetPhase">phase</functionlink>).
+    Some classes might not be compatible
     with the function (eg. ROMized classes) and this event will not be
     generated for these classes.
     <p/>
@@ -12378,9 +12408,7 @@
     using the memory allocation function 
     <functionlink id="Allocate"></functionlink> because the
     VM is responsible for freeing the new class file data buffer
-    using <functionlink id="Deallocate"></functionlink>.  
-    Note that <functionlink id="Allocate"></functionlink>
-    is permitted during the primordial phase.
+    using <functionlink id="Deallocate"></functionlink>.
     <p/>
     If the agent wishes to modify the class file, it must set 
     <code>new_class_data</code> to point
@@ -12427,8 +12455,6 @@
         </outptr>
           <description>
             The JNI environment of the event (current) thread.
-	    Will be <code>NULL</code> if sent during the primordial 
-            <functionlink id="GetPhase">phase</functionlink>.
           </description>
       </param>
       <param id="class_being_redefined">
@@ -14340,6 +14366,12 @@
   <change date="19 June 2013" version="1.2.3">
       Added support for statically linked agents.
   </change>
+  <change date="20 January 2016" version="9.0.0">
+      Support for modules:
+       - The majorversion is 9 now
+       - The ClassFileLoadHook events are not sent during the primordial phase anymore.
+       - Add new function GetAllModules
+  </change>
 </changehistory>
 
 </specification>
--- a/src/share/vm/prims/jvmtiEnv.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -186,6 +186,20 @@
 } /* end GetThreadLocalStorage */
 
   //
+  // Module functions
+  //
+
+// module_count_ptr - pre-checked for NULL
+// modules_ptr - pre-checked for NULL
+jvmtiError
+JvmtiEnv::GetAllModules(jint* module_count_ptr, jobject** modules_ptr) {
+    JvmtiModuleClosure jmc;
+
+    return jmc.get_all_modules(this, module_count_ptr, modules_ptr);
+} /* end GetAllModules */
+
+
+  //
   // Class functions
   //
 
--- a/src/share/vm/prims/jvmtiEnvBase.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -1475,3 +1475,35 @@
     }
   }
 }
+
+GrowableArray<jobject>* JvmtiModuleClosure::_tbl = NULL;
+
+jvmtiError
+JvmtiModuleClosure::get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr) {
+  ResourceMark rm;
+  MutexLocker ml(Module_lock);
+
+  _tbl = new GrowableArray<jobject>(77);
+  if (_tbl == NULL) {
+    return JVMTI_ERROR_OUT_OF_MEMORY;
+  }
+
+  // Iterate over all the modules loaded to the system.
+  ClassLoaderDataGraph::modules_do(&do_module);
+
+  jint len = _tbl->length();
+  guarantee(len > 0, "at least one module must be present");
+
+  jobject* array = (jobject*)env->jvmtiMalloc((jlong)(len * sizeof(jobject)));
+  if (array == NULL) {
+    return JVMTI_ERROR_OUT_OF_MEMORY;
+  }
+  for (jint idx = 0; idx < len; idx++) {
+    array[idx] = _tbl->at(idx);
+  }
+  _tbl = NULL;
+  *modules_ptr = array;
+  *module_count_ptr = len;
+  return JVMTI_ERROR_NONE;
+}
+
--- a/src/share/vm/prims/jvmtiEnvBase.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmtiEnvBase.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -689,4 +689,21 @@
   jvmtiError error() { return _error;}
 };
 
+
+// Jvmti module closure to collect all modules loaded to the system.
+class JvmtiModuleClosure : public StackObj {
+private:
+  static GrowableArray<jobject> *_tbl; // Protected with Module_lock
+
+  static void do_module(ModuleEntry* entry) {
+    assert_locked_or_safepoint(Module_lock);
+    jobject module = entry->jlrM_module();
+    guarantee(module != NULL, "module object is NULL");
+    _tbl->push(module);
+  }
+
+public:
+  jvmtiError get_all_modules(JvmtiEnv* env, jint* module_count_ptr, jobject** modules_ptr);
+};
+
 #endif // SHARE_VM_PRIMS_JVMTIENVBASE_HPP
--- a/src/share/vm/prims/jvmtiExport.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmtiExport.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -46,6 +46,7 @@
 #include "runtime/arguments.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/javaCalls.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/os.inline.hpp"
@@ -369,6 +370,14 @@
           return JNI_EVERSION;  // unsupported minor version number
       }
       break;
+    case 9:
+      switch (minor) {
+        case 0:  // version 9.0.<micro> is recognized
+          break;
+        default:
+          return JNI_EVERSION;  // unsupported minor version number
+      }
+      break;
     default:
       return JNI_EVERSION;  // unsupported major version number
   }
@@ -397,6 +406,28 @@
   }
 }
 
+void
+JvmtiExport::add_default_read_edges(Handle h_module, TRAPS) {
+  if (!Universe::is_module_initialized()) {
+    return; // extra safety
+  }
+  assert(!h_module.is_null(), "module should always be set");
+
+  // Invoke the transformedByAgent method
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::module_Modules_klass(),
+                         vmSymbols::transformedByAgent_name(),
+                         vmSymbols::transformedByAgent_signature(),
+                         h_module,
+                         THREAD);
+
+  if (HAS_PENDING_EXCEPTION) {
+    java_lang_Throwable::print(PENDING_EXCEPTION, tty);
+    CLEAR_PENDING_EXCEPTION;
+    return;
+  }
+}
 
 void
 JvmtiExport::decode_version_values(jint version, int * major, int * minor,
@@ -544,6 +575,21 @@
     if (_state != NULL) {
       _h_class_being_redefined = _state->get_class_being_redefined();
       _load_kind = _state->get_class_load_kind();
+      Klass* klass = (_h_class_being_redefined == NULL) ? NULL : (*_h_class_being_redefined)();
+      if (_load_kind != jvmti_class_load_kind_load && klass != NULL) {
+        ModuleEntry* module_entry = InstanceKlass::cast(klass)->module();
+        assert(module_entry != NULL, "module_entry should always be set");
+        if (module_entry->is_named() &&
+            module_entry->jlrM_module() != NULL &&
+            !module_entry->has_default_read_edges()) {
+          if (!module_entry->set_has_default_read_edges()) {
+            // We won a potential race.
+            // Add read edges to the unnamed modules of the bootstrap and app class loaders
+            Handle class_module(_thread, JNIHandles::resolve(module_entry->jlrM_module())); // Obtain j.l.r.Module
+            JvmtiExport::add_default_read_edges(class_module, _thread);
+          }
+        }
+      }
       // Clear class_being_redefined flag here. The action
       // from agent handler could generate a new class file load
       // hook event and if it is not cleared the new event generated
@@ -668,6 +714,10 @@
                                             unsigned char **data_ptr,
                                             unsigned char **end_ptr,
                                             JvmtiCachedClassFileData **cache_ptr) {
+  if (JvmtiEnv::get_phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
+
   JvmtiClassFileLoadHookPoster poster(h_name, class_loader,
                                       h_protection_domain,
                                       data_ptr, end_ptr,
@@ -912,6 +962,9 @@
 }
 
 void JvmtiExport::post_class_load(JavaThread *thread, Klass* klass) {
+  if (JvmtiEnv::get_phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   HandleMark hm(thread);
   KlassHandle kh(thread, klass);
 
@@ -941,6 +994,9 @@
 
 
 void JvmtiExport::post_class_prepare(JavaThread *thread, Klass* klass) {
+  if (JvmtiEnv::get_phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   HandleMark hm(thread);
   KlassHandle kh(thread, klass);
 
@@ -969,6 +1025,9 @@
 }
 
 void JvmtiExport::post_class_unload(Klass* klass) {
+  if (JvmtiEnv::get_phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   Thread *thread = Thread::current();
   HandleMark hm(thread);
   KlassHandle kh(thread, klass);
@@ -1018,6 +1077,9 @@
 
 
 void JvmtiExport::post_thread_start(JavaThread *thread) {
+  if (JvmtiEnv::get_phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   assert(thread->thread_state() == _thread_in_vm, "must be in vm state");
 
   EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Trg Thread Start event triggered",
@@ -1048,6 +1110,9 @@
 
 
 void JvmtiExport::post_thread_end(JavaThread *thread) {
+  if (JvmtiEnv::get_phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   EVT_TRIG_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Trg Thread End event triggered",
                       JvmtiTrace::safe_get_thread_name(thread)));
 
--- a/src/share/vm/prims/jvmtiExport.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmtiExport.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -213,6 +213,8 @@
     _all_dependencies_are_recorded = (on != 0);
   }
 
+  // Add read edges to the unnamed modules of the bootstrap and app class loaders
+  static void add_default_read_edges(Handle h_module, TRAPS) NOT_JVMTI_RETURN;
 
   // let JVMTI know that the JVM_OnLoad code is running
   static void enter_onload_phase() NOT_JVMTI_RETURN;
--- a/src/share/vm/prims/jvmtiH.xsl	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/jvmtiH.xsl	Thu Feb 18 11:41:21 2016 -0800
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -113,6 +113,7 @@
     JVMTI_VERSION_1_0 = 0x30010000,
     JVMTI_VERSION_1_1 = 0x30010100,
     JVMTI_VERSION_1_2 = 0x30010200,
+    JVMTI_VERSION_9   = 0x30090000,
 
     JVMTI_VERSION = 0x30000000 + (</xsl:text>
   <xsl:value-of select="//specification/@majorversion"/>
--- a/src/share/vm/prims/methodHandles.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/methodHandles.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1185,9 +1185,9 @@
     if (reference_klass != NULL && reference_klass->is_instance_klass()) {
       // Emulate LinkResolver::check_klass_accessability.
       Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
-      if (!Reflection::verify_class_access(caller,
-                                           reference_klass,
-                                           true)) {
+      if (Reflection::verify_class_access(caller,
+                                          reference_klass,
+                                          true) != Reflection::ACCESS_OK) {
         THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name());
       }
     }
--- a/src/share/vm/prims/whitebox.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/prims/whitebox.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -27,6 +27,7 @@
 #include <new>
 
 #include "classfile/classLoaderData.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/stringTable.hpp"
 #include "code/codeCache.hpp"
 #include "compiler/methodMatcher.hpp"
@@ -1249,6 +1250,39 @@
   MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
 WB_END
 
+WB_ENTRY(void, WB_DefineModule(JNIEnv* env, jobject o, jobject module, jstring version, jstring location,
+                                jobjectArray packages))
+  Modules::define_module(env, module, version, location, packages);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
+  Modules::add_module_exports_qualified(env, from_module, package, to_module);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_exports_to_all_unnamed(env, module, package);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_exports(env, module, package, NULL);
+WB_END
+
+WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
+  Modules::add_reads_module(env, from_module, source_module);
+WB_END
+
+WB_ENTRY(jboolean, WB_CanReadModule(JNIEnv* env, jobject o, jobject asking_module, jobject source_module))
+  return Modules::can_read_module(env, asking_module, source_module);
+WB_END
+
+WB_ENTRY(jboolean, WB_IsExportedToModule(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
+  return Modules::is_exported_to_module(env, from_module, package, to_module);
+WB_END
+
+WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_package(env, module, package);
+WB_END
+
 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
   if (inc < 0) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -1277,7 +1311,6 @@
 WB_END
 
 
-
 WB_ENTRY(void, WB_AssertMatchingSafepointCalls(JNIEnv* env, jobject o, jboolean mutexSafepointValue, jboolean attemptedNoSafepointValue))
   Monitor::SafepointCheckRequired sfpt_check_required = mutexSafepointValue ?
                                            Monitor::_safepoint_check_always :
@@ -1286,10 +1319,6 @@
                    attemptedNoSafepointValue == JNI_TRUE);
 WB_END
 
-WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
-  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
-WB_END
-
 WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj))
   oop obj_oop = JNIHandles::resolve(obj);
   return (jboolean) obj_oop->mark()->has_monitor();
@@ -1384,6 +1413,10 @@
   return MetaspaceShared::is_in_shared_space((void*)obj_oop);
 WB_END
 
+WB_ENTRY(jboolean, WB_IsSharedClass(JNIEnv* env, jobject wb, jclass clazz))
+  return (jboolean)MetaspaceShared::is_in_shared_space(java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz)));
+WB_END
+
 WB_ENTRY(jboolean, WB_AreSharedStringsIgnored(JNIEnv* env))
   return StringTable::shared_string_ignored();
 WB_END
@@ -1495,10 +1528,9 @@
   {CC"runMemoryUnitTests", CC"()V",                   (void*)&WB_RunMemoryUnitTests},
   {CC"readFromNoaccessArea",CC"()V",                  (void*)&WB_ReadFromNoaccessArea},
   {CC"stressVirtualSpaceResize",CC"(JJJ)I",           (void*)&WB_StressVirtualSpaceResize},
-  {CC"isSharedClass", CC"(Ljava/lang/Class;)Z",       (void*)&WB_IsSharedClass },
 #if INCLUDE_ALL_GCS
   {CC"g1InConcurrentMark", CC"()Z",                   (void*)&WB_G1InConcurrentMark},
-  {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z",(void*)&WB_G1IsHumongous     },
+  {CC"g1IsHumongous0",      CC"(Ljava/lang/Object;)Z", (void*)&WB_G1IsHumongous     },
   {CC"g1BelongsToHumongousRegion0", CC"(J)Z",         (void*)&WB_G1BelongsToHumongousRegion},
   {CC"g1BelongsToFreeRegion0", CC"(J)Z",              (void*)&WB_G1BelongsToFreeRegion},
   {CC"g1NumMaxRegions",    CC"()J",                   (void*)&WB_G1NumMaxRegions  },
@@ -1616,6 +1648,22 @@
   {CC"getCodeBlob",        CC"(J)[Ljava/lang/Object;",(void*)&WB_GetCodeBlob        },
   {CC"getThreadStackSize", CC"()J",                   (void*)&WB_GetThreadStackSize },
   {CC"getThreadRemainingStackSize", CC"()J",          (void*)&WB_GetThreadRemainingStackSize },
+  {CC"DefineModule",       CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Object;)V",
+                                                      (void*)&WB_DefineModule },
+  {CC"AddModuleExports",   CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)V",
+                                                      (void*)&WB_AddModuleExports },
+  {CC"AddReadsModule",     CC"(Ljava/lang/Object;Ljava/lang/Object;)V",
+                                                      (void*)&WB_AddReadsModule },
+  {CC"CanReadModule",      CC"(Ljava/lang/Object;Ljava/lang/Object;)Z",
+                                                      (void*)&WB_CanReadModule },
+  {CC"IsExportedToModule", CC"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Z",
+                                                      (void*)&WB_IsExportedToModule },
+  {CC"AddModulePackage",   CC"(Ljava/lang/Object;Ljava/lang/String;)V",
+                                                      (void*)&WB_AddModulePackage },
+  {CC"AddModuleExportsToAllUnnamed", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
+                                                      (void*)&WB_AddModuleExportsToAllUnnamed },
+  {CC"AddModuleExportsToAll", CC"(Ljava/lang/Object;Ljava/lang/String;)V",
+                                                      (void*)&WB_AddModuleExportsToAll },
   {CC"assertMatchingSafepointCalls", CC"(ZZ)V",       (void*)&WB_AssertMatchingSafepointCalls },
   {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated  },
   {CC"forceSafepoint",     CC"()V",                   (void*)&WB_ForceSafepoint     },
@@ -1636,6 +1684,7 @@
       CC"(Ljava/lang/reflect/Executable;Ljava/lang/String;)Ljava/lang/String;",
                                                       (void*)&WB_GetMethodStringOption},
   {CC"isShared",           CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared },
+  {CC"isSharedClass",      CC"(Ljava/lang/Class;)Z",  (void*)&WB_IsSharedClass },
   {CC"areSharedStringsIgnored",           CC"()Z",    (void*)&WB_AreSharedStringsIgnored },
   {CC"clearInlineCaches",  CC"()V",                   (void*)&WB_ClearInlineCaches },
 };
--- a/src/share/vm/runtime/arguments.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/arguments.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -93,6 +93,9 @@
 const char*  Arguments::_sun_java_launcher      = DEFAULT_JAVA_LAUNCHER;
 int    Arguments::_sun_java_launcher_pid        = -1;
 bool   Arguments::_sun_java_launcher_is_altjvm  = false;
+int    Arguments::_patch_dirs_count          = 0;
+char** Arguments::_patch_dirs                = NULL;
+int    Arguments::_bootclassloader_append_index = -1;
 
 // These parameters are reset in method parse_vm_init_args()
 bool   Arguments::_AlwaysCompileLoopMethods     = AlwaysCompileLoopMethods;
@@ -117,6 +120,7 @@
 SystemProperty *Arguments::_java_home = NULL;
 SystemProperty *Arguments::_java_class_path = NULL;
 SystemProperty *Arguments::_sun_boot_class_path = NULL;
+SystemProperty *Arguments::_jdk_boot_class_path_append = NULL;
 
 char* Arguments::_ext_dirs = NULL;
 
@@ -207,8 +211,15 @@
   _sun_boot_library_path = new SystemProperty("sun.boot.library.path", NULL,  true);
   _java_library_path = new SystemProperty("java.library.path", NULL,  true);
   _java_home =  new SystemProperty("java.home", NULL,  true);
+  // Do not add sun.boot.class.path to the PropertyList because its JDK value
+  // should be NULL in JDK-9.  But, keep it internally because its value is used
+  // by the JVM.
   _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL,  true);
 
+  // jdk.boot.class.path.append will only get set if -XX+bootclass/a: is specified.
+  // So, make sure it is initialized with a non-null value.
+  _jdk_boot_class_path_append = new SystemProperty("jdk.boot.class.path.append", "", true);
+
   _java_class_path = new SystemProperty("java.class.path", "",  true);
 
   // Add to System Property list.
@@ -216,7 +227,8 @@
   PropertyList_add(&_system_properties, _java_library_path);
   PropertyList_add(&_system_properties, _java_home);
   PropertyList_add(&_system_properties, _java_class_path);
-  PropertyList_add(&_system_properties, _sun_boot_class_path);
+
+  PropertyList_add(&_system_properties, _jdk_boot_class_path_append);
 
   // Set OS specific system properties values
   os::init_system_properties_values();
@@ -364,7 +376,6 @@
   { "AdaptiveSizePausePolicy",       JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "ParallelGCRetainPLAB",          JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "ThreadSafetyMargin",            JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
-  { "LazyBootClassLoader",           JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "StarvationMonitorInterval",     JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "PreInflateSpin",                JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
   { "JNIDetachReleasesMonitors",     JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) },
@@ -537,8 +548,8 @@
 // Constructs the system class path (aka boot class path) from the following
 // components, in order:
 //
-//     prefix           // from -Xbootclasspath/p:...
-//     base             // from os::get_system_properties() or -Xbootclasspath=
+//     prefix           // from -Xpatch:...
+//     base             // from os::get_system_properties()
 //     suffix           // from -Xbootclasspath/a:...
 //
 // This could be AllStatic, but it isn't needed after argument processing is
@@ -572,7 +583,7 @@
   // Array indices for the items that make up the sysclasspath.  All except the
   // base are allocated in the C heap and freed by this class.
   enum {
-    _scp_prefix,        // from -Xbootclasspath/p:...
+    _scp_prefix,        // was -Xpatch:...
     _scp_base,          // the default sysclasspath
     _scp_suffix,        // from -Xbootclasspath/a:...
     _scp_nitems         // the number of items, must be last.
@@ -640,6 +651,10 @@
   // Get the lengths.
   int i;
   for (i = 0; i < _scp_nitems; ++i) {
+    if (i == _scp_suffix) {
+      // Record index of boot loader's append path.
+      Arguments::set_bootclassloader_append_index((int)total_len);
+    }
     if (_items[i] != NULL) {
       lengths[i] = strlen(_items[i]);
       // Include space for the separator char (or a NULL for the last item).
@@ -1367,6 +1382,54 @@
   return true;
 }
 
+// sets or adds a module name to the jdk.launcher.addmods property
+bool Arguments::append_to_addmods_property(const char* module_name) {
+  const char* key = "jdk.launcher.addmods";
+  const char* old_value = Arguments::get_property(key);
+  size_t buf_len = strlen(key) + strlen(module_name) + 2;
+  if (old_value != NULL) {
+    buf_len += strlen(old_value) + 1;
+  }
+  char* new_value = AllocateHeap(buf_len, mtInternal);
+  if (new_value == NULL) {
+    return false;
+  }
+  if (old_value == NULL) {
+    jio_snprintf(new_value, buf_len, "%s=%s", key, module_name);
+  } else {
+    jio_snprintf(new_value, buf_len, "%s=%s,%s", key, old_value, module_name);
+  }
+  bool added = add_property(new_value);
+  FreeHeap(new_value);
+  return added;
+}
+
+#if INCLUDE_CDS
+void Arguments::check_unsupported_dumping_properties() {
+  assert(DumpSharedSpaces, "this function is only used with -Xshare:dump");
+  const char* unsupported_properties[5] = { "jdk.module.main",
+                                           "jdk.module.path",
+                                           "jdk.upgrade.module.path",
+                                           "jdk.launcher.addmods",
+                                           "jdk.launcher.limitmods" };
+  const char* unsupported_options[5] = { "-m",
+                                        "-modulepath",
+                                        "-upgrademodulepath",
+                                        "-addmods",
+                                        "-limitmods" };
+  SystemProperty* sp = system_properties();
+  while (sp != NULL) {
+    for (int i = 0; i < 5; i++) {
+      if (strcmp(sp->key(), unsupported_properties[i]) == 0) {
+          vm_exit_during_initialization(
+            "Cannot use the following option when dumping the shared archive", unsupported_options[i]);
+      }
+    }
+    sp = sp->next();
+  }
+}
+#endif
+
 //===========================================================================================================
 // Setting int/mixed/comp mode flags
 
@@ -2682,16 +2745,18 @@
       JavaAssertions::setSystemClassDefault(enable);
     // -bootclasspath:
     } else if (match_option(option, "-Xbootclasspath:", &tail)) {
-      scp_p->reset_path(tail);
-      *scp_assembly_required_p = true;
+        jio_fprintf(defaultStream::output_stream(),
+          "-Xbootclasspath is no longer a supported option.\n");
+        return JNI_EINVAL;
     // -bootclasspath/a:
     } else if (match_option(option, "-Xbootclasspath/a:", &tail)) {
       scp_p->add_suffix(tail);
       *scp_assembly_required_p = true;
     // -bootclasspath/p:
     } else if (match_option(option, "-Xbootclasspath/p:", &tail)) {
-      scp_p->add_prefix(tail);
-      *scp_assembly_required_p = true;
+        jio_fprintf(defaultStream::output_stream(),
+          "-Xbootclasspath/p is no longer a supported option.\n");
+        return JNI_EINVAL;
     // -Xrun
     } else if (match_option(option, "-Xrun", &tail)) {
       if (tail != NULL) {
@@ -2743,9 +2808,14 @@
         "Instrumentation agents are not supported in this VM\n");
       return JNI_ERR;
 #else
-      if(tail != NULL) {
+      if (tail != NULL) {
         char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail);
         add_init_agent("instrument", options, false);
+        // java agents need module java.instrument. Also -addmods ALL-SYSTEM because
+        // the java agent is in the unmamed module of the application class loader
+        if (!Arguments::append_to_addmods_property("java.instrument,ALL-SYSTEM")) {
+          return JNI_ENOMEM;
+        }
       }
 #endif // !INCLUDE_JVMTI
     // -Xnoclassgc
@@ -3011,12 +3081,50 @@
         if (FLAG_SET_CMDLINE(bool, ManagementServer, true) != Flag::SUCCESS) {
           return JNI_EINVAL;
         }
+        // management agent in module java.management
+        if (!Arguments::append_to_addmods_property("java.management")) {
+          return JNI_ENOMEM;
+        }
 #else
         jio_fprintf(defaultStream::output_stream(),
           "-Dcom.sun.management is not supported in this VM.\n");
         return JNI_ERR;
 #endif
       }
+      if (match_option(option, "-Djdk.launcher.patch=", &tail)) {
+        // -Xpatch
+        int dir_count;
+        char** patch_dirs = os::split_path(tail, &dir_count);
+        if (patch_dirs == NULL) {
+          jio_fprintf(defaultStream::output_stream(),
+            "Bad value for -Xpatch.\n");
+          return JNI_ERR;
+        }
+        set_patch_dirs(patch_dirs);
+        set_patch_dirs_count(dir_count);
+
+        // Create a path for each patch dir consisting of dir/java.base.
+        char file_sep = os::file_separator()[0];
+        for (int x = 0; x < dir_count; x++) {
+          // Really shouldn't be NULL, but check can't hurt
+          if (patch_dirs[x] != NULL) {
+            size_t len = strlen(patch_dirs[x]);
+            if (len != 0) { // Ignore empty strings.
+              len += 11; // file_sep + "java.base" + null terminator.
+              char* dir = NEW_C_HEAP_ARRAY(char, len, mtInternal);
+              jio_snprintf(dir, len, "%s%cjava.base", patch_dirs[x], file_sep);
+
+              // See if Xpatch module path exists.
+              struct stat st;
+              if ((os::stat(dir, &st) == 0)) {
+                scp_p->add_prefix(dir);
+                *scp_assembly_required_p = true;
+              }
+              FREE_C_HEAP_ARRAY(char, dir);
+            }
+          }
+        }
+      }
     // -Xint
     } else if (match_option(option, "-Xint")) {
           set_mode_flags(_int);
@@ -3274,6 +3382,18 @@
   return JNI_OK;
 }
 
+// Set property jdk.boot.class.path.append to the contents of the bootclasspath
+// that follows either the jimage file or exploded module directories.  The
+// property will contain -Xbootclasspath/a and/or jvmti appended additions.
+void Arguments::set_jdkbootclasspath_append() {
+  char *sysclasspath = get_sysclasspath();
+  assert(sysclasspath != NULL, "NULL sysclasspath");
+  int bcp_a_idx = bootclassloader_append_index();
+  if (bcp_a_idx != -1 && bcp_a_idx < (int)strlen(sysclasspath)) {
+    _jdk_boot_class_path_append->set_value(sysclasspath + bcp_a_idx);
+  }
+}
+
 // Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled)
 //
 // This is necessary because some apps like to specify classpath like -cp foo.jar:${XYZ}:bar.jar
@@ -3405,6 +3525,11 @@
     char *combined_path = scp_p->combined_path();
     Arguments::set_sysclasspath(combined_path);
     FREE_C_HEAP_ARRAY(char, combined_path);
+  } else {
+    // At this point in sysclasspath processing anything
+    // added would be considered in the boot loader's append path.
+    // Record this index, including +1 for the file separator character.
+    Arguments::set_bootclassloader_append_index(((int)strlen(Arguments::get_sysclasspath()))+1);
   }
 
   // This must be done after all arguments have been processed.
@@ -3750,6 +3875,11 @@
 
 void Arguments::set_shared_spaces_flags() {
   if (DumpSharedSpaces) {
+    if (Arguments::patch_dirs() != NULL) {
+      vm_exit_during_initialization(
+        "Cannot use the following option when dumping the shared archive", "-Xpatch");
+    }
+
     if (RequireSharedSpaces) {
       warning("Cannot dump shared archive while using shared archive");
     }
--- a/src/share/vm/runtime/arguments.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/arguments.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -274,6 +274,7 @@
   static SystemProperty *_java_home;
   static SystemProperty *_java_class_path;
   static SystemProperty *_sun_boot_class_path;
+  static SystemProperty *_jdk_boot_class_path_append;
 
   // temporary: to emit warning if the default ext dirs are not empty.
   // remove this variable when the warning is no longer needed.
@@ -297,7 +298,7 @@
   // Value of the conservative maximum heap alignment needed
   static size_t  _conservative_max_heap_alignment;
 
-  static uintx _min_heap_size;
+  static uintx  _min_heap_size;
 
   // -Xrun arguments
   static AgentLibraryList _libraryList;
@@ -322,6 +323,17 @@
   static void set_java_compiler(bool arg) { _java_compiler = arg; }
   static bool java_compiler()   { return _java_compiler; }
 
+  // Capture the index location of -Xbootclasspath\a within sysclasspath.
+  // Used when setting up the bootstrap search path in order to
+  // mark the boot loader's append path observability boundary.
+  static int _bootclassloader_append_index;
+
+  // -Xpatch flag
+  static char** _patch_dirs;
+  static int _patch_dirs_count;
+  static void set_patch_dirs(char** dirs) { _patch_dirs = dirs; }
+  static void set_patch_dirs_count(int count) { _patch_dirs_count = count; }
+
   // -Xdebug flag
   static bool _xdebug_mode;
   static void set_xdebug_mode(bool arg) { _xdebug_mode = arg; }
@@ -372,6 +384,9 @@
   // System properties
   static bool add_property(const char* prop);
 
+  // Miscellaneous system property setter
+  static bool append_to_addmods_property(const char* module_name);
+
   // Aggressive optimization flags.
   static jint set_aggressive_opts_flags();
 
@@ -563,6 +578,18 @@
   static size_t min_heap_size()             { return _min_heap_size; }
   static void  set_min_heap_size(size_t v)  { _min_heap_size = v;  }
 
+  // -Xbootclasspath/a
+  static int  bootclassloader_append_index() {
+    return _bootclassloader_append_index;
+  }
+  static void set_bootclassloader_append_index(int value) {
+    _bootclassloader_append_index = value;
+  }
+
+  // -Xpatch
+  static char** patch_dirs()             { return _patch_dirs; }
+  static int patch_dirs_count()          { return _patch_dirs_count; }
+
   // -Xrun
   static AgentLibrary* libraries()          { return _libraryList.first(); }
   static bool init_libraries_at_startup()   { return !_libraryList.is_empty(); }
@@ -619,8 +646,15 @@
   static void set_java_home(const char *value) { _java_home->set_value(value); }
   static void set_library_path(const char *value) { _java_library_path->set_value(value); }
   static void set_ext_dirs(char *value)     { _ext_dirs = os::strdup_check_oom(value); }
-  static void set_sysclasspath(const char *value) { _sun_boot_class_path->set_value(value); }
-  static void append_sysclasspath(const char *value) { _sun_boot_class_path->append_value(value); }
+  static void set_jdkbootclasspath_append();
+  static void set_sysclasspath(const char *value) {
+    _sun_boot_class_path->set_value(value);
+    set_jdkbootclasspath_append();
+  }
+  static void append_sysclasspath(const char *value) {
+    _sun_boot_class_path->append_value(value);
+    set_jdkbootclasspath_append();
+  }
 
   static char* get_java_home() { return _java_home->value(); }
   static char* get_dll_dir() { return _sun_boot_library_path->value(); }
@@ -631,12 +665,14 @@
 
 
   // Operation modi
-  static Mode mode()                { return _mode; }
+  static Mode mode()                        { return _mode; }
   static bool is_interpreter_only() { return mode() == _int; }
 
 
   // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid.
   static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen);
+
+  static void check_unsupported_dumping_properties() NOT_CDS_RETURN;
 };
 
 bool Arguments::gc_selected() {
--- a/src/share/vm/runtime/frame.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/frame.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -642,6 +642,13 @@
         m->name_and_sig_as_C_string(buf, buflen);
         st->print("j  %s", buf);
         st->print("+%d", this->interpreter_frame_bci());
+        ModuleEntry* module = m->method_holder()->module();
+        if (module->is_named()) {
+          module->name()->as_C_string(buf, buflen);
+          st->print(" %s", buf);
+          module->version()->as_C_string(buf, buflen);
+          st->print("@%s", buf);
+        }
       } else {
         st->print("j  " PTR_FORMAT, p2i(pc()));
       }
@@ -668,8 +675,15 @@
           st->print(" (%s)", jvmciName);
         }
 #endif
-        st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
-                  buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
+        ModuleEntry* module = m->method_holder()->module();
+        if (module->is_named()) {
+          module->name()->as_C_string(buf, buflen);
+          st->print(" %s", buf);
+          module->version()->as_C_string(buf, buflen);
+          st->print("@%s", buf);
+        }
+        st->print("(%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]",
+                   m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin());
       } else {
         st->print("J  " PTR_FORMAT, p2i(pc()));
       }
--- a/src/share/vm/runtime/jniHandles.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/jniHandles.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -471,6 +471,14 @@
   return allocate_handle(obj);  // retry
 }
 
+void JNIHandleBlock::release_handle(jobject h) {
+  if (h != NULL) {
+    assert(chain_contains(h), "does not contain the JNI handle");
+    // Mark the handle as deleted, allocate will reuse it
+    *((oop*)h) = JNIHandles::deleted_handle();
+  }
+}
+
 
 void JNIHandleBlock::rebuild_free_list() {
   assert(_allocate_before_rebuild == 0 && _free_list == NULL, "just checking");
--- a/src/share/vm/runtime/jniHandles.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/jniHandles.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -138,6 +138,9 @@
   // Handle allocation
   jobject allocate_handle(oop obj);
 
+  // Release Handle
+  void release_handle(jobject);
+
   // Block allocation and block free list management
   static JNIHandleBlock* allocate_block(Thread* thread = NULL);
   static void release_block(JNIHandleBlock* block, Thread* thread = NULL);
--- a/src/share/vm/runtime/mutexLocker.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/mutexLocker.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,7 @@
 
 Mutex*   Patching_lock                = NULL;
 Monitor* SystemDictionary_lock        = NULL;
-Mutex*   PackageTable_lock            = NULL;
+Mutex*   Module_lock                  = NULL;
 Mutex*   CompiledIC_lock              = NULL;
 Mutex*   InlineCacheBuffer_lock       = NULL;
 Mutex*   VMStatistic_lock             = NULL;
@@ -216,7 +216,7 @@
   def(JmethodIdCreation_lock       , Mutex  , leaf,        true,  Monitor::_safepoint_check_always);     // used for creating jmethodIDs.
 
   def(SystemDictionary_lock        , Monitor, leaf,        true,  Monitor::_safepoint_check_always);     // lookups done by VM thread
-  def(PackageTable_lock            , Mutex  , leaf,        false, Monitor::_safepoint_check_always);
+  def(Module_lock                  , Mutex  , leaf+2,      true,  Monitor::_safepoint_check_always);
   def(InlineCacheBuffer_lock       , Mutex  , leaf,        true,  Monitor::_safepoint_check_always);
   def(VMStatistic_lock             , Mutex  , leaf,        false, Monitor::_safepoint_check_always);
   def(ExpandHeap_lock              , Mutex  , leaf,        true,  Monitor::_safepoint_check_always);     // Used during compilation by VM thread
--- a/src/share/vm/runtime/mutexLocker.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/mutexLocker.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -32,7 +32,7 @@
 
 extern Mutex*   Patching_lock;                   // a lock used to guard code patching of compiled code
 extern Monitor* SystemDictionary_lock;           // a lock on the system dictionary
-extern Mutex*   PackageTable_lock;               // a lock on the class loader package table
+extern Mutex*   Module_lock;                     // a lock on module related data structures
 extern Mutex*   CompiledIC_lock;                 // a lock used to guard compiled IC patching and access
 extern Mutex*   InlineCacheBuffer_lock;          // a lock used to guard the InlineCacheBuffer
 extern Mutex*   VMStatistic_lock;                // a lock used to guard statistics count increment
--- a/src/share/vm/runtime/os.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/os.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1193,67 +1193,14 @@
     return formatted_path;
 }
 
-// returns a PATH of all entries in the given directory that do not start with a '.'
-static char* expand_entries_to_path(char* directory, char fileSep, char pathSep) {
-  DIR* dir = os::opendir(directory);
-  if (dir == NULL) return NULL;
-
-  char* path = NULL;
-  size_t path_len = 0;  // path length including \0 terminator
-
-  size_t directory_len = strlen(directory);
-  struct dirent *entry;
-  char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
-  while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
-    const char* name = entry->d_name;
-    if (name[0] == '.') continue;
-
-    size_t name_len = strlen(name);
-    size_t needed = directory_len + name_len + 2;
-    size_t new_len = path_len + needed;
-    if (path == NULL) {
-      path = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
-    } else {
-      path = REALLOC_C_HEAP_ARRAY(char, path, new_len, mtInternal);
-    }
-    if (path == NULL)
-      break;
-
-    // append <pathSep>directory<fileSep>name
-    char* p = path;
-    if (path_len > 0) {
-      p += (path_len -1);
-      *p = pathSep;
-      p++;
-    }
-
-    strcpy(p, directory);
-    p += directory_len;
-
-    *p = fileSep;
-    p++;
-
-    strcpy(p, name);
-    p += name_len;
-
-    path_len = new_len;
-  }
-
-  FREE_C_HEAP_ARRAY(char, dbuf);
-  os::closedir(dir);
-
-  return path;
-}
-
 bool os::set_boot_path(char fileSep, char pathSep) {
   const char* home = Arguments::get_java_home();
   int home_len = (int)strlen(home);
 
-  char* sysclasspath = NULL;
   struct stat st;
 
-  // modular image if bootmodules.jimage exists
-  char* jimage = format_boot_path("%/lib/modules/" BOOT_IMAGE_NAME, home, home_len, fileSep, pathSep);
+  // modular image if "modules" jimage exists
+  char* jimage = format_boot_path("%/lib/" MODULES_IMAGE_NAME, home, home_len, fileSep, pathSep);
   if (jimage == NULL) return false;
   bool has_jimage = (os::stat(jimage, &st) == 0);
   if (has_jimage) {
@@ -1264,23 +1211,16 @@
   FREE_C_HEAP_ARRAY(char, jimage);
 
   // check if developer build with exploded modules
-  char* modules_dir = format_boot_path("%/modules", home, home_len, fileSep, pathSep);
-  if (os::stat(modules_dir, &st) == 0) {
-    if ((st.st_mode & S_IFDIR) == S_IFDIR) {
-      sysclasspath = expand_entries_to_path(modules_dir, fileSep, pathSep);
-    }
+  char* base_classes = format_boot_path("%/modules/java.base", home, home_len, fileSep, pathSep);
+  if (base_classes == NULL) return false;
+  if (os::stat(base_classes, &st) == 0) {
+    Arguments::set_sysclasspath(base_classes);
+    FREE_C_HEAP_ARRAY(char, base_classes);
+    return true;
   }
-  FREE_C_HEAP_ARRAY(char, modules_dir);
+  FREE_C_HEAP_ARRAY(char, base_classes);
 
-  // fallback to classes
-  if (sysclasspath == NULL)
-    sysclasspath = format_boot_path("%/classes", home, home_len, fileSep, pathSep);
-
-  if (sysclasspath == NULL) return false;
-  Arguments::set_sysclasspath(sysclasspath);
-  FREE_C_HEAP_ARRAY(char, sysclasspath);
-
-  return true;
+  return false;
 }
 
 /*
--- a/src/share/vm/runtime/os.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/os.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -776,6 +776,8 @@
   // Amount beyond the callee frame size that we bang the stack.
   static int extra_bang_size_in_bytes();
 
+  static char** split_path(const char* path, int* n);
+
   // Extensions
 #include "runtime/os_ext.hpp"
 
@@ -991,7 +993,6 @@
                                 char fileSep,
                                 char pathSep);
   static bool set_boot_path(char fileSep, char pathSep);
-  static char** split_path(const char* path, int* n);
 
 };
 
--- a/src/share/vm/runtime/reflection.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/reflection.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,8 @@
 
 #include "precompiled.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
+#include "classfile/packageEntry.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/verifier.hpp"
@@ -452,25 +454,183 @@
   return false;
 }
 
-bool Reflection::verify_class_access(const Klass* current_class,
-                                     const Klass* new_class,
-                                     bool classloader_only) {
+/*
+    Type Accessibility check for public types: Callee Type T is accessible to Caller Type S if:
+
+                        Callee T in             Callee T in package PT,
+                        unnamed module          runtime module MT
+ ------------------------------------------------------------------------------------------------
+
+ Caller S in package     If MS is loose: YES      If same classloader/package (PS == PT): YES
+ PS, runtime module MS   If MS can read T's       If same runtime module: (MS == MT): YES
+                         unnamed module: YES
+                                                  Else if (MS can read MT (Establish readability) &&
+                                                    MT exports PT to MS or to all modules): YES
+
+ ------------------------------------------------------------------------------------------------
+ Caller S in unnamed         YES                  Readability exists because unnamed module
+ module UM                                            "reads" all modules
+                                                  if (MT exports PT to UM or to all modules): YES
+
+ ------------------------------------------------------------------------------------------------
+
+ Note: a loose module is a module that can read all current and future unnamed modules.
+*/
+Reflection::VerifyClassAccessResults Reflection::verify_class_access(
+  const Klass* current_class, const Klass* new_class, bool classloader_only) {
+
   // Verify that current_class can access new_class.  If the classloader_only
   // flag is set, we automatically allow any accesses in which current_class
   // doesn't have a classloader.
   if ((current_class == NULL) ||
       (current_class == new_class) ||
-      (new_class->is_public()) ||
       is_same_class_package(current_class, new_class)) {
-    return true;
+    return ACCESS_OK;
   }
   // Allow all accesses from sun/reflect/MagicAccessorImpl subclasses to
   // succeed trivially.
   if (current_class->is_subclass_of(SystemDictionary::reflect_MagicAccessorImpl_klass())) {
-    return true;
+    return ACCESS_OK;
   }
 
-  return can_relax_access_check_for(current_class, new_class, classloader_only);
+  // module boundaries
+  if (new_class->is_public()) {
+    // Ignore modules for DumpSharedSpaces because we do not have any package
+    // or module information for modules other than java.base.
+    if (DumpSharedSpaces) {
+      return ACCESS_OK;
+    }
+
+    // Find the module entry for current_class, the accessor
+    ModuleEntry* module_from = InstanceKlass::cast(current_class)->module();
+    // Find the module entry for new_class, the accessee
+    if (new_class->is_objArray_klass()) {
+      new_class = ObjArrayKlass::cast(new_class)->bottom_klass();
+    }
+    if (!new_class->is_instance_klass()) {
+      // Everyone can read a typearray.
+      assert (new_class->is_typeArray_klass(), "Unexpected klass type");
+      return ACCESS_OK;
+    }
+    ModuleEntry* module_to = InstanceKlass::cast(new_class)->module();
+
+    // both in same (possibly unnamed) module
+    if (module_from == module_to)
+      return ACCESS_OK;
+
+    // Acceptable access to a type in an unamed module.  Note that since
+    // unnamed modules can read all unnamed modules, this also handles the
+    // case where module_from is also unnamed but in a different class loader.
+    if (!module_to->is_named() &&
+        (module_from->can_read_all_unnamed() || module_from->can_read(module_to)))
+      return ACCESS_OK;
+
+    // Establish readability, check if module_from is allowed to read module_to.
+    if (!module_from->can_read(module_to)) {
+      return MODULE_NOT_READABLE;
+    }
+
+    PackageEntry* package_to = InstanceKlass::cast(new_class)->package();
+    assert(package_to != NULL, "can not obtain new_class' package");
+
+    // Once readability is established, if module_to exports T unqualifiedly,
+    // (to all modules), than whether module_from is in the unnamed module
+    // or not does not matter, access is allowed.
+    if (package_to->is_unqual_exported()) {
+      return ACCESS_OK;
+    }
+
+    // Access is allowed if both 1 & 2 hold:
+    //   1. Readability, module_from can read module_to (established above).
+    //   2. Either module_to exports T to module_from qualifiedly.
+    //      or
+    //      module_to exports T to all unnamed modules and module_from is unnamed.
+    //      or
+    //      module_to exports T unqualifiedly to all modules (checked above).
+    if (!package_to->is_qexported_to(module_from)) {
+      return TYPE_NOT_EXPORTED;
+    }
+    return ACCESS_OK;
+  }
+
+  if (can_relax_access_check_for(current_class, new_class, classloader_only)) {
+    return ACCESS_OK;
+  }
+  return OTHER_PROBLEM;
+}
+
+// Return an error message specific to the specified Klass*'s and result.
+// This function must be called from within a block containing a ResourceMark.
+char* Reflection::verify_class_access_msg(const Klass* current_class,
+                                          const Klass* new_class,
+                                          VerifyClassAccessResults result) {
+  assert(result != ACCESS_OK, "must be failure result");
+  char * msg = NULL;
+  if (result != OTHER_PROBLEM && new_class != NULL && current_class != NULL) {
+    ModuleEntry* module_to = InstanceKlass::cast(new_class)->module();
+    const char * new_class_name = new_class->external_name();
+    const char * current_class_name = current_class->external_name();
+    const char * module_to_name = module_to->is_named() ?
+      module_to->name()->as_C_string() : UNNAMED_MODULE;
+
+    ModuleEntry* module_from = InstanceKlass::cast(current_class)->module();
+    const char * module_from_name = module_from->is_named() ?
+      module_from->name()->as_C_string() : UNNAMED_MODULE;
+
+    if (result == MODULE_NOT_READABLE) {
+      assert(module_from->is_named(), "Unnamed modules can read all modules");
+      if (module_to->is_named()) {
+        size_t len = 100 + strlen(current_class_name) + 2*strlen(module_from_name) +
+          strlen(new_class_name) + 2*strlen(module_to_name);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in module %s) cannot access class %s (in module %s) because module %s does not read module %s",
+          current_class_name, module_from_name, new_class_name,
+          module_to_name, module_from_name, module_to_name);
+      } else {
+        jobject jlrm = module_to->jlrM_module();
+        assert(jlrm != NULL, "Null jlrm in module_to ModuleEntry");
+        intptr_t identity_hash = JNIHandles::resolve(jlrm)->identity_hash();
+        size_t len = 160 + strlen(current_class_name) + 2*strlen(module_from_name) +
+          strlen(new_class_name) + 2*sizeof(uintx);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in module %s) cannot access class %s (in unnamed module @" SIZE_FORMAT_HEX ") because module %s does not read unnamed module @" SIZE_FORMAT_HEX,
+          current_class_name, module_from_name, new_class_name, uintx(identity_hash),
+          module_from_name, uintx(identity_hash));
+      }
+
+    } else if (result == TYPE_NOT_EXPORTED) {
+      assert(InstanceKlass::cast(new_class)->package() != NULL,
+             "Unnamed packages are always exported");
+      const char * package_name =
+        InstanceKlass::cast(new_class)->package()->name()->as_klass_external_name();
+      assert(module_to->is_named(), "Unnamed modules export all packages");
+      if (module_from->is_named()) {
+        size_t len = 118 + strlen(current_class_name) + 2*strlen(module_from_name) +
+          strlen(new_class_name) + 2*strlen(module_to_name) + strlen(package_name);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in module %s) cannot access class %s (in module %s) because module %s does not export %s to module %s",
+          current_class_name, module_from_name, new_class_name,
+          module_to_name, module_to_name, package_name, module_from_name);
+      } else {
+        jobject jlrm = module_from->jlrM_module();
+        assert(jlrm != NULL, "Null jlrm in module_from ModuleEntry");
+        intptr_t identity_hash = JNIHandles::resolve(jlrm)->identity_hash();
+        size_t len = 170 + strlen(current_class_name) + strlen(new_class_name) +
+          2*strlen(module_to_name) + strlen(package_name) + 2*sizeof(uintx);
+        msg = NEW_RESOURCE_ARRAY(char, len);
+        jio_snprintf(msg, len - 1,
+          "class %s (in unnamed module @" SIZE_FORMAT_HEX ") cannot access class %s (in module %s) because module %s does not export %s to unnamed module @" SIZE_FORMAT_HEX,
+          current_class_name, uintx(identity_hash), new_class_name, module_to_name,
+          module_to_name, package_name, uintx(identity_hash));
+      }
+    } else {
+        ShouldNotReachHere();
+    }
+  }  // result != OTHER_PROBLEM...
+  return msg;
 }
 
 bool Reflection::verify_field_access(const Klass* current_class,
--- a/src/share/vm/runtime/reflection.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/reflection.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -53,6 +53,14 @@
     MAX_DIM           = 255
   };
 
+  // Results returned by verify_class_access()
+  enum VerifyClassAccessResults {
+    ACCESS_OK = 0,
+    MODULE_NOT_READABLE = 1,
+    TYPE_NOT_EXPORTED = 2,
+    OTHER_PROBLEM = 3
+  };
+
   // Boxing. Returns boxed value of appropriate type. Throws IllegalArgumentException.
   static oop box(jvalue* v, BasicType type, TRAPS);
   // Unboxing. Returns type code and sets value.
@@ -73,9 +81,14 @@
   static arrayOop reflect_new_multi_array(oop element_mirror, typeArrayOop dimensions, TRAPS);
 
   // Verification
-  static bool     verify_class_access(const Klass* current_class,
-                                      const Klass* new_class,
-                                      bool classloader_only);
+  static VerifyClassAccessResults verify_class_access(const Klass* current_class,
+                                                      const Klass* new_class,
+                                                      bool classloader_only);
+  // Return an error message specific to the specified Klass*'s and result.
+  // This function must be called from within a block containing a ResourceMark.
+  static char*    verify_class_access_msg(const Klass* current_class,
+                                          const Klass* new_class,
+                                          const VerifyClassAccessResults result);
 
   static bool     verify_field_access(const Klass* current_class,
                                       const Klass* resolved_class,
--- a/src/share/vm/runtime/sharedRuntime.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/sharedRuntime.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -39,6 +39,8 @@
 #include "interpreter/interpreterRuntime.hpp"
 #include "logging/log.hpp"
 #include "memory/universe.inline.hpp"
+#include "oops/klass.hpp"
+#include "oops/objArrayKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/forte.hpp"
 #include "prims/jvmtiExport.hpp"
@@ -1908,28 +1910,58 @@
 }
 JRT_END
 
+// The caller of generate_class_cast_message() (or one of its callers)
+// must use a ResourceMark in order to correctly free the result.
 char* SharedRuntime::generate_class_cast_message(
-    JavaThread* thread, const char* objName) {
+    JavaThread* thread, Klass* caster_klass) {
 
   // Get target class name from the checkcast instruction
   vframeStream vfst(thread, true);
   assert(!vfst.at_end(), "Java frame must exist");
   Bytecode_checkcast cc(vfst.method(), vfst.method()->bcp_from(vfst.bci()));
-  Klass* targetKlass = vfst.method()->constants()->klass_at(
+  Klass* target_klass = vfst.method()->constants()->klass_at(
     cc.index(), thread);
-  return generate_class_cast_message(objName, targetKlass->external_name());
+  return generate_class_cast_message(caster_klass, target_klass);
 }
 
 char* SharedRuntime::generate_class_cast_message(
-    const char* objName, const char* targetKlassName, const char* desc) {
-  size_t msglen = strlen(objName) + strlen(desc) + strlen(targetKlassName) + 1;
+    Klass* caster_klass, Klass* target_klass) {
+
+  const char* caster_klass_name = caster_klass->external_name();
+  Klass* c_klass = caster_klass->is_objArray_klass() ?
+    ObjArrayKlass::cast(caster_klass)->bottom_klass() : caster_klass;
+  ModuleEntry* caster_module;
+  const char* caster_module_name;
+  if (c_klass->is_instance_klass()) {
+    caster_module = InstanceKlass::cast(c_klass)->module();
+    caster_module_name = caster_module->is_named() ?
+      caster_module->name()->as_C_string() : UNNAMED_MODULE;
+  } else {
+    caster_module_name = "java.base";
+  }
+  const char* target_klass_name = target_klass->external_name();
+  Klass* t_klass = target_klass->is_objArray_klass() ?
+    ObjArrayKlass::cast(target_klass)->bottom_klass() : target_klass;
+  ModuleEntry* target_module;
+  const char* target_module_name;
+  if (t_klass->is_instance_klass()) {
+    target_module = InstanceKlass::cast(t_klass)->module();
+    target_module_name = target_module->is_named() ?
+      target_module->name()->as_C_string(): UNNAMED_MODULE;
+  } else {
+    target_module_name = "java.base";
+  }
+
+  size_t msglen = strlen(caster_klass_name) + strlen(caster_module_name) +
+     strlen(target_klass_name) + strlen(target_module_name) + 50;
 
   char* message = NEW_RESOURCE_ARRAY(char, msglen);
   if (NULL == message) {
     // Shouldn't happen, but don't cause even more problems if it does
-    message = const_cast<char*>(objName);
+    message = const_cast<char*>(caster_klass_name);
   } else {
-    jio_snprintf(message, msglen, "%s%s%s", objName, desc, targetKlassName);
+    jio_snprintf(message, msglen, "%s (in module: %s) cannot be cast to %s (in module: %s)",
+      caster_klass_name, caster_module_name, target_klass_name, target_module_name);
   }
   return message;
 }
--- a/src/share/vm/runtime/sharedRuntime.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/sharedRuntime.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -293,22 +293,21 @@
   // Fill in the "X cannot be cast to a Y" message for ClassCastException
   //
   // @param thr the current thread
-  // @param name the name of the class of the object attempted to be cast
+  // @param caster_klass the class of the object we are casting
   // @return the dynamically allocated exception message (must be freed
   // by the caller using a resource mark)
   //
   // BCP must refer to the current 'checkcast' opcode for the frame
   // on top of the stack.
-  // The caller (or one of it's callers) must use a ResourceMark
+  // The caller (or one of its callers) must use a ResourceMark
   // in order to correctly free the result.
   //
-  static char* generate_class_cast_message(JavaThread* thr, const char* name);
+  static char* generate_class_cast_message(JavaThread* thr, Klass* caster_klass);
 
   // Fill in the "X cannot be cast to a Y" message for ClassCastException
   //
-  // @param name the name of the class of the object attempted to be cast
-  // @param klass the name of the target klass attempt
-  // @param gripe the specific kind of problem being reported
+  // @param caster_klass the class of the object we are casting
+  // @param target_klass the target klass attempt
   // @return the dynamically allocated exception message (must be freed
   // by the caller using a resource mark)
   //
@@ -317,8 +316,7 @@
   // The caller (or one of it's callers) must use a ResourceMark
   // in order to correctly free the result.
   //
-  static char* generate_class_cast_message(const char* name, const char* klass,
-                                           const char* gripe = " cannot be cast to ");
+  static char* generate_class_cast_message(Klass* caster_klass, Klass* target_klass);
 
   // Resolves a call site- may patch in the destination of the call into the
   // compiled code.
--- a/src/share/vm/runtime/statSampler.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/statSampler.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -238,7 +238,6 @@
 
 // unstable interface, unsupported counters
 static const char* property_counters_uu[] = {
-  "sun.boot.class.path",
   "sun.boot.library.path",
   NULL
 };
--- a/src/share/vm/runtime/thread.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/thread.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/classLoader.hpp"
 #include "classfile/javaClasses.hpp"
+#include "classfile/moduleEntry.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/codeCache.hpp"
@@ -116,6 +117,9 @@
 #include "runtime/rtmLocking.hpp"
 #endif
 
+// Initialization after module runtime initialization
+void universe_post_module_init();  // must happen after call_initPhase2
+
 #ifdef DTRACE_ENABLED
 
 // Only bother with this argument setup if dtrace is available
@@ -992,15 +996,6 @@
   return thread_oop();
 }
 
-static void call_initializeSystemClass(TRAPS) {
-  Klass* k =  SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
-  instanceKlassHandle klass (THREAD, k);
-
-  JavaValue result(T_VOID);
-  JavaCalls::call_static(&result, klass, vmSymbols::initializeSystemClass_name(),
-                         vmSymbols::void_method_signature(), CHECK);
-}
-
 char java_runtime_name[128] = "";
 char java_runtime_version[128] = "";
 
@@ -3325,6 +3320,62 @@
   // If CompilerThreads ever become non-JavaThreads, add them here
 }
 
+// The system initialization in the library has three phases.
+//
+// Phase 1: java.lang.System class initialization
+//     java.lang.System is a primordial class loaded and initialized
+//     by the VM early during startup.  java.lang.System.<clinit>
+//     only does registerNatives and keeps the rest of the class
+//     initialization work later until thread initialization completes.
+//
+//     System.initPhase1 initializes the system properties, the static
+//     fields in, out, and err. Set up java signal handlers, OS-specific
+//     system settings, and thread group of the main thread.
+static void call_initPhase1(TRAPS) {
+  Klass* k =  SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
+  instanceKlassHandle klass (THREAD, k);
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbols::initPhase1_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
+}
+
+// Phase 2. Module system initialization
+//     This will initialize the module system.  Only java.base classes
+//     can be loaded until phase 2 completes.
+//
+//     Call System.initPhase2 after the compiler initialization and jsr292
+//     classes get initialized because module initialization runs a lot of java
+//     code, that for performance reasons, should be compiled.  Also, this will
+//     enable the startup code to use lambda and other language features in this
+//     phase and onward.
+//
+//     After phase 2, The VM will begin search classes from -Xbootclasspath/a.
+static void call_initPhase2(TRAPS) {
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
+  instanceKlassHandle klass (THREAD, k);
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbols::initPhase2_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
+  universe_post_module_init();
+}
+
+// Phase 3. final setup - set security manager, system class loader and TCCL
+//
+//     This will instantiate and set the security manager, set the system class
+//     loader as well as the thread context class loader.  The security manager
+//     and system class loader may be a custom class loaded from -Xbootclasspath/a,
+//     other modules or the application's classpath.
+static void call_initPhase3(TRAPS) {
+  Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_System(), true, CHECK);
+  instanceKlassHandle klass (THREAD, k);
+
+  JavaValue result(T_VOID);
+  JavaCalls::call_static(&result, klass, vmSymbols::initPhase3_name(),
+                                         vmSymbols::void_method_signature(), CHECK);
+}
+
 void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) {
   TraceTime timer("Initialize java.lang classes", TraceStartupTime);
 
@@ -3352,10 +3403,15 @@
   java_lang_Thread::set_thread_status(thread_object,
                                       java_lang_Thread::RUNNABLE);
 
+  // The VM creates objects of this class.
+  initialize_class(vmSymbols::java_lang_reflect_Module(), CHECK);
+
   // The VM preresolves methods to these classes. Make sure that they get initialized
   initialize_class(vmSymbols::java_lang_reflect_Method(), CHECK);
   initialize_class(vmSymbols::java_lang_ref_Finalizer(), CHECK);
-  call_initializeSystemClass(CHECK);
+
+  // Phase 1 of the system initialization in the library, java.lang.System class initialization
+  call_initPhase1(CHECK);
 
   // get the Java runtime name after java.lang.System is initialized
   JDK_Version::set_runtime_name(get_java_runtime_name(THREAD));
@@ -3564,13 +3620,6 @@
     ShouldNotReachHere();
   }
 
-  // Always call even when there are not JVMTI environments yet, since environments
-  // may be attached late and JVMTI must track phases of VM execution
-  JvmtiExport::enter_start_phase();
-
-  // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents.
-  JvmtiExport::post_vm_start();
-
   initialize_java_lang_classes(main_thread, CHECK_JNI_ERR);
 
   // We need this for ClassDataSharing - the initial vm.info property is set
@@ -3599,12 +3648,9 @@
   Management::record_vm_init_completed();
 #endif // INCLUDE_MANAGEMENT
 
-  // Compute system loader. Note that this has to occur after set_init_completed, since
-  // valid exceptions may be thrown in the process.
   // Note that we do not use CHECK_0 here since we are inside an EXCEPTION_MARK and
   // set_init_completed has just been called, causing exceptions not to be shortcut
   // anymore. We call vm_exit_during_initialization directly instead.
-  SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
 
 #if INCLUDE_ALL_GCS
   // Support for ConcurrentMarkSweep. This should be cleaned up
@@ -3619,10 +3665,6 @@
   }
 #endif // INCLUDE_ALL_GCS
 
-  // Always call even when there are not JVMTI environments yet, since environments
-  // may be attached late and JVMTI must track phases of VM execution
-  JvmtiExport::enter_live_phase();
-
   // Signal Dispatcher needs to be started before VMInit event is posted
   os::signal_init();
 
@@ -3641,13 +3683,6 @@
     create_vm_init_libraries();
   }
 
-  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
-  JvmtiExport::post_vm_initialized();
-
-  if (TRACE_START() != JNI_OK) {
-    vm_exit_during_initialization("Failed to start tracing backend.");
-  }
-
   if (CleanChunkPoolAsync) {
     Chunk::start_chunk_pool_cleaner_task();
   }
@@ -3672,6 +3707,34 @@
   // (see SystemDictionary::find_method_handle_intrinsic).
   initialize_jsr292_core_classes(CHECK_JNI_ERR);
 
+  // This will initialize the module system.  Only java.base classes can be
+  // loaded until phase 2 completes
+  call_initPhase2(CHECK_JNI_ERR);
+
+  // Always call even when there are not JVMTI environments yet, since environments
+  // may be attached late and JVMTI must track phases of VM execution
+  JvmtiExport::enter_start_phase();
+
+  // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents.
+  JvmtiExport::post_vm_start();
+
+  // Final system initialization including security manager and system class loader
+  call_initPhase3(CHECK_JNI_ERR);
+
+  // cache the system class loader
+  SystemDictionary::compute_java_system_loader(CHECK_(JNI_ERR));
+
+  // Always call even when there are not JVMTI environments yet, since environments
+  // may be attached late and JVMTI must track phases of VM execution
+  JvmtiExport::enter_live_phase();
+
+  if (TRACE_START() != JNI_OK) {
+    vm_exit_during_initialization("Failed to start tracing backend.");
+  }
+
+  // Notify JVMTI agents that VM initialization is complete - nop if no agents.
+  JvmtiExport::post_vm_initialized();
+
 #if INCLUDE_MANAGEMENT
   Management::initialize(THREAD);
 
--- a/src/share/vm/runtime/vmStructs.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/runtime/vmStructs.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1354,10 +1354,11 @@
   /* java_lang_Class fields        */                                                                                                \
   /*********************************/                                                                                                \
                                                                                                                                      \
-     static_field(java_lang_Class,             _klass_offset,                                 int)                                   \
-     static_field(java_lang_Class,             _array_klass_offset,                           int)                                   \
-     static_field(java_lang_Class,             _oop_size_offset,                              int)                                   \
-     static_field(java_lang_Class,             _static_oop_field_count_offset,                int)                                   \
+  static_field(java_lang_Class,                _klass_offset,                                 int)                                   \
+  static_field(java_lang_Class,                _array_klass_offset,                           int)                                   \
+  static_field(java_lang_Class,                _oop_size_offset,                              int)                                   \
+  static_field(java_lang_Class,                _static_oop_field_count_offset,                int)                                   \
+  static_field(java_lang_Class,                _module_offset,                                int)                                   \
                                                                                                                                      \
   /************************/                                                                                                         \
   /* Miscellaneous fields */                                                                                                         \
--- a/src/share/vm/services/jmm.h	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/services/jmm.h	Thu Feb 18 11:41:21 2016 -0800
@@ -59,7 +59,6 @@
   unsigned int isThreadContentionMonitoringSupported : 1;
   unsigned int isCurrentThreadCpuTimeSupported : 1;
   unsigned int isOtherThreadCpuTimeSupported : 1;
-  unsigned int isBootClassPathSupported : 1;
   unsigned int isObjectMonitorUsageSupported : 1;
   unsigned int isSynchronizerUsageSupported : 1;
   unsigned int isThreadAllocatedMemorySupported : 1;
--- a/src/share/vm/services/management.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/services/management.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -121,7 +121,6 @@
     _optional_support.isOtherThreadCpuTimeSupported = 0;
   }
 
-  _optional_support.isBootClassPathSupported = 1;
   _optional_support.isObjectMonitorUsageSupported = 1;
 #if INCLUDE_SERVICES
   // This depends on the heap inspector
--- a/src/share/vm/trace/traceDataTypes.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/trace/traceDataTypes.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -58,12 +58,11 @@
 
 typedef enum ReservedEvent ReservedEvent;
 
-typedef u8 classid;
-typedef u8 stacktraceid;
-typedef u8 methodid;
-typedef u8 fieldid;
+typedef u8 traceid;
 
+class ModuleEntry;
+class PackageEntry;
 class TraceUnicodeString;
+class Symbol;
 
 #endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP
-
--- a/src/share/vm/trace/traceMacros.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/trace/traceMacros.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -28,16 +28,18 @@
 #define EVENT_THREAD_EXIT(thread)
 #define EVENT_THREAD_DESTRUCT(thread)
 
-#define TRACE_INIT_ID(k)
+#define TRACE_INIT_KLASS_ID(k)
+#define TRACE_INIT_MODULE_ID(m)
+#define TRACE_INIT_PACKAGE_ID(p)
 #define TRACE_DATA TraceThreadData
 
 #define TRACE_START() JNI_OK
 #define TRACE_INITIALIZE() JNI_OK
 
-#define TRACE_DEFINE_KLASS_METHODS typedef int ___IGNORED_hs_trace_type1
-#define TRACE_DEFINE_KLASS_TRACE_ID typedef int ___IGNORED_hs_trace_type2
-#define TRACE_DEFINE_OFFSET typedef int ___IGNORED_hs_trace_type3
-#define TRACE_ID_OFFSET in_ByteSize(0); ShouldNotReachHere()
+#define TRACE_DEFINE_TRACE_ID_METHODS typedef int ___IGNORED_hs_trace_type1
+#define TRACE_DEFINE_TRACE_ID_FIELD typedef int ___IGNORED_hs_trace_type2
+#define TRACE_DEFINE_KLASS_TRACE_ID_OFFSET typedef int ___IGNORED_hs_trace_type3
+#define TRACE_KLASS_TRACE_ID_OFFSET in_ByteSize(0); ShouldNotReachHere()
 #define TRACE_TEMPLATES(template)
 #define TRACE_INTRINSICS(do_intrinsic, do_class, do_name, do_signature, do_alias)
 
--- a/src/share/vm/trace/traceTypes.xsl	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/trace/traceTypes.xsl	Thu Feb 18 11:41:21 2016 -0800
@@ -32,7 +32,6 @@
 #ifndef TRACEFILES_TRACETYPES_HPP
 #define TRACEFILES_TRACETYPES_HPP
 
-#include "oops/symbol.hpp"
 #include "trace/traceDataTypes.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/ticks.hpp"
--- a/src/share/vm/trace/tracetypes.xml	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/trace/tracetypes.xml	Thu Feb 18 11:41:21 2016 -0800
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
- Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
  DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 
  This code is free software; you can redistribute it and/or modify it
@@ -89,6 +89,7 @@
                   type="U8" builtin_type="CLASS">
       <value type="CLASS" field="loaderClass" label="ClassLoader"/>
       <value type="SYMBOL" field="name" label="Name"/>
+      <value type="PACKAGE" field="package" label="Package"/>
       <value type="SHORT" field="modifiers" label="Access modifiers"/>
     </content_type>
 
@@ -176,6 +177,20 @@
       <value type="UTF8" field="type" label="type" />
     </content_type>
 
+    <content_type id="Module" hr_name="Module"
+              type="U8" jvm_type="MODULE">
+      <value type="SYMBOL" field="name" label="Name"/>
+      <value type="SYMBOL" field="version" label="Version"/>
+      <value type="SYMBOL" field="location" label="Location"/>
+      <value type="CLASS" field="classLoader" label="ClassLoader"/>
+    </content_type>
+
+    <content_type id="Package" hr_name="Package"
+              type="U8" jvm_type="PACKAGE">
+      <value type="SYMBOL" field="name" label="Name"/>
+      <value type="MODULE" field="module" label="Module"/>
+      <value type="BOOLEAN" field="exported" label="Exported"/>
+    </content_type>
   </content_types>
 
 
@@ -292,6 +307,12 @@
     <primary_type symbol="CLASS" datatype="U8" contenttype="CLASS"
                   type="Klass *" sizeop="sizeof(u8)"/>
 
+    <primary_type symbol="MODULE" datatype="U8" contenttype="MODULE"
+                  type="const ModuleEntry *" sizeop="sizeof(u8)"/>
+
+    <primary_type symbol="PACKAGE" datatype="U8" contenttype="PACKAGE"
+              type="const PackageEntry *" sizeop="sizeof(u8)"/>
+
     <!-- A Method *. The method is marked as "used" and will eventually be
          written into the recording constant pool. -->
     <primary_type symbol="METHOD" datatype="U8" contenttype="METHOD"
--- a/src/share/vm/utilities/dtrace_disabled.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/utilities/dtrace_disabled.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -1084,6 +1084,12 @@
 #define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN(arg0)
 #define HOTSPOT_JNI_UNREGISTERNATIVES_RETURN_ENABLED()  0
 
+/* Modules */
+#define HOTSPOT_JNI_GETMODULE_ENTRY(arg0, arg1)
+#define HOTSPOT_JNI_GETMODULE_ENTRY_ENABLED()  0
+#define HOTSPOT_JNI_GETMODULE_RETURN(arg0)
+#define HOTSPOT_JNI_GETMODULE_RETURN_ENABLED()
+
 #else /* !defined(DTRACE_ENABLED) */
 #error This file should only be included when dtrace is not enabled
 #endif /* !defined(DTRACE_ENABLED) */
--- a/src/share/vm/utilities/ostream.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/utilities/ostream.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -693,8 +693,10 @@
       for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
         // Print in two stages to avoid problems with long
         // keys/values.
+        assert(p->key() != NULL, "p->key() is NULL");
         text->print_raw(p->key());
         text->put('=');
+        assert(p->value() != NULL, "p->value() is NULL");
         text->print_raw_cr(p->value());
       }
       xs->tail("properties");
--- a/src/share/vm/utilities/utf8.cpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/utilities/utf8.cpp	Thu Feb 18 11:41:21 2016 -0800
@@ -333,6 +333,68 @@
                  + ((str[4] & 0x0f) << 6)  + (str[5] & 0x3f);
 }
 
+bool UTF8::is_legal_utf8(const unsigned char* buffer, int length,
+                         bool version_leq_47) {
+  int i = 0;
+  int count = length >> 2;
+  for (int k=0; k<count; k++) {
+    unsigned char b0 = buffer[i];
+    unsigned char b1 = buffer[i+1];
+    unsigned char b2 = buffer[i+2];
+    unsigned char b3 = buffer[i+3];
+    // For an unsigned char v,
+    // (v | v - 1) is < 128 (highest bit 0) for 0 < v < 128;
+    // (v | v - 1) is >= 128 (highest bit 1) for v == 0 or v >= 128.
+    unsigned char res = b0 | b0 - 1 |
+                        b1 | b1 - 1 |
+                        b2 | b2 - 1 |
+                        b3 | b3 - 1;
+    if (res >= 128) break;
+    i += 4;
+  }
+  for(; i < length; i++) {
+    unsigned short c;
+    // no embedded zeros
+    if (buffer[i] == 0) return false;
+    if(buffer[i] < 128) {
+      continue;
+    }
+    if ((i + 5) < length) { // see if it's legal supplementary character
+      if (UTF8::is_supplementary_character(&buffer[i])) {
+        c = UTF8::get_supplementary_character(&buffer[i]);
+        i += 5;
+        continue;
+      }
+    }
+    switch (buffer[i] >> 4) {
+      default: break;
+      case 0x8: case 0x9: case 0xA: case 0xB: case 0xF:
+        return false;
+      case 0xC: case 0xD:  // 110xxxxx  10xxxxxx
+        c = (buffer[i] & 0x1F) << 6;
+        i++;
+        if ((i < length) && ((buffer[i] & 0xC0) == 0x80)) {
+          c += buffer[i] & 0x3F;
+          if (version_leq_47 || c == 0 || c >= 0x80) {
+            break;
+          }
+        }
+        return false;
+      case 0xE:  // 1110xxxx 10xxxxxx 10xxxxxx
+        c = (buffer[i] & 0xF) << 12;
+        i += 2;
+        if ((i < length) && ((buffer[i-1] & 0xC0) == 0x80) && ((buffer[i] & 0xC0) == 0x80)) {
+          c += ((buffer[i-1] & 0x3F) << 6) + (buffer[i] & 0x3F);
+          if (version_leq_47 || c >= 0x800) {
+            break;
+          }
+        }
+        return false;
+    }  // end of switch
+  } // end of for
+  return true;
+}
+
 //-------------------------------------------------------------------------------------
 
 bool UNICODE::is_latin1(jchar c) {
--- a/src/share/vm/utilities/utf8.hpp	Fri Feb 12 11:07:46 2016 +0100
+++ b/src/share/vm/utilities/utf8.hpp	Thu Feb 18 11:41:21 2016 -0800
@@ -73,6 +73,9 @@
   static bool   equal(const jbyte* base1, int length1, const jbyte* base2,int length2);
   static bool   is_supplementary_character(const unsigned char* str);
   static jint   get_supplementary_character(const unsigned char* str);
+
+  static bool   is_legal_utf8(const unsigned char* buffer, int length,
+                              bool version_leq_47);
 };
 
 
--- a/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,9 +24,10 @@
 /*
  * @test
  * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @build compiler.calls.common.InvokeDynamic
  * @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *    sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,9 +24,10 @@
 /*
  * @test
  * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @build compiler.calls.common.InvokeDynamic
  * @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *    sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,9 +24,10 @@
 /*
  * @test
  * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @build compiler.calls.common.InvokeDynamic
  * @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *    sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,9 +24,10 @@
 /*
  * @test
  * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @build compiler.calls.common.InvokeDynamic
  * @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *    sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,9 +24,10 @@
 /*
  * @test
  * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @build compiler.calls.common.InvokeDynamic
  * @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *    sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,9 +24,10 @@
 /*
  * @test
  * @library /test/lib /testlibrary /
+ * @modules java.base/jdk.internal.org.objectweb.asm
  * @build compiler.calls.common.InvokeDynamic
  * @build compiler.calls.common.InvokeDynamicPatcher
- * @run driver compiler.calls.common.InvokeDynamicPatcher
+ * @run main compiler.calls.common.InvokeDynamicPatcher
  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  *    sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
--- a/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java	Thu Feb 18 11:41:21 2016 -0800
@@ -22,6 +22,8 @@
  */
 
 import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
 
@@ -35,11 +37,11 @@
  * @modules java.base/sun.misc
  *          java.management
  *          java.base/jdk.internal
+ * @ignore 8132924
  * @compile -XDignore.symbol.file java/lang/Object.java TestMonomorphicObjectCall.java
  * @run main TestMonomorphicObjectCall
  */
 public class TestMonomorphicObjectCall {
-    final static String testClasses = System.getProperty("test.classes") + File.separator;
 
     private static void callFinalize(Object object) throws Throwable {
         // Call modified version of java.lang.Object::finalize() that is
@@ -50,6 +52,9 @@
 
     public static void main(String[] args) throws Throwable {
         if (args.length == 0) {
+            byte[] bytecode = Files.readAllBytes(Paths.get(System.getProperty("test.classes") + File.separator +
+                "java" + File.separator + "lang" + File.separator + "Object.class"));
+            ClassFileInstaller.writeClassToDisk("java.lang.Object", bytecode, "mods/java.base");
             // Execute new instance with modified java.lang.Object
             executeTestJvm();
         } else {
@@ -62,7 +67,7 @@
         // Execute test with modified version of java.lang.Object
         // in -Xbootclasspath.
         String[] vmOpts = new String[] {
-                "-Xbootclasspath/p:" + testClasses,
+                "-Xpatch:mods",
                 "-Xcomp",
                 "-XX:+IgnoreUnrecognizedVMOptions",
                 "-XX:-VerifyDependencies",
--- a/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/intrinsics/classcast/NullCheckDroppingsTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -28,6 +28,7 @@
  * @library /testlibrary /test/lib
  * @modules java.base/sun.misc
  *          java.management
+ *          jdk.jvmstat/sun.jvmstat.monitor
  * @build ClassFileInstaller sun.hotspot.WhiteBox jdk.test.lib.*
  * @build NullCheckDroppingsTest
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
--- a/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java	Thu Feb 18 11:41:21 2016 -0800
@@ -26,6 +26,7 @@
  * @test
  * @bug 8136473
  * @summary Mismatched stores on same slice possible with Unsafe.Put*Unaligned methods
+ * @modules java.base/jdk.internal.misc
  * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestUnsafeUnalignedMismatchedAccesses
  * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses TestUnsafeUnalignedMismatchedAccesses
  *
--- a/test/compiler/jsr292/CallSiteDepContextTest.java	Fri Feb 12 11:07:46 2016 +0100
+++ b/test/compiler/jsr292/CallSiteDepContextTest.java	Thu Feb 18 11:41:21 2016 -0800
@@ -24,13 +24,25 @@
 /**
  * @test
  * @bug 8057967
+ * @modules java.base/jdk.internal.org.objectweb.asm
+ * @library patches
+ * @build java.base/java.lang.invoke.MethodHandleHelper
  * @run main/bootclasspath -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+TraceClassUnloading
  *                         -XX:+PrintCompilation -XX:+TraceDependencies -XX:+TraceReferenceGC
- *                         -verbose:gc java.lang.invoke.CallSiteDepContextTest
+ *                         -verbose:gc compiler.jsr292.CallSiteDepContextTest
  */
-package java.lang.invoke;
 
-import java.lang.ref.*;
+package compiler.jsr292;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandleHelper;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.lang.ref.PhantomReference;
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
 import java.lang.reflect.Field;
 
 import jdk.internal.org.objectweb.asm.*;
@@ -40,10 +52,10 @@
 
 public class CallSiteDepContextTest {
     static final Unsafe               UNSAFE = Unsafe.getUnsafe();
-    static final MethodHandles.Lookup LOOKUP = MethodHandles.Lookup.IMPL_LOOKUP;
+    static final MethodHandles.Lookup LOOKUP = MethodHandleHelper.IMPL_LOOKUP;
     static final String           CLASS_NAME = "java/lang/invoke/Test";
     static final String          METHOD_NAME = "m";