changeset 10487:c558850fac57 jdk-9+111

8142968: Module System implementation Summary: Initial integration of JEP 200, JEP 260, JEP 261, and JEP 282 Reviewed-by: acorn, ccheung, coleenp, ctornqvi, dholmes, dsimms, gtriantafill, iklam, jiangli, mgronlun, mseledtsov, cjplummer, sspitsyn, stefank, twisti, hseigel, lfoltan, alanb, mchung, dfazunen Contributed-by: alan.bateman@oracle.com, alex.buckley@oracle.com, jonathan.gibbons@oracle.com, karen.kinnear@oracle.com, mandy.chung@oracle.com, mark.reinhold@oracle.com, harold.seigel@oracle.com, lois.foltan@oracle.com, calvin.cheung@oracle.com, christian.tornqvist@oracle.com, erik.joelsson@oracle.com, george.triantafillou@oracle.com, igor.ignatyev@oracle.com, ioi.lam@oracle.com, james.laskey@oracle.com, jean-francois.denise@oracle.com, jiangli.zhou@oracle.com, markus.gronlund@oracle.com, serguei.spitsyn@oracle.com, staffan.larsen@oracle.com, sundararajan.athijegannathan@oracle.com
author alanb
date Thu, 17 Mar 2016 19:04:01 +0000
parents 0de4d895a5c8
children ffee6483b81b cf67bfa444b1
files make/share/makefiles/mapfile-vers make/test/JtregNative.gmk src/jdk.hotspot.agent/share/classes/module-info.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java src/jdk.vm.ci/share/classes/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory src/jdk.vm.ci/share/classes/module-info.java src/os/posix/dtrace/hotspot_jni.d src/share/vm/c1/c1_Runtime1.cpp src/share/vm/ci/ciEnv.cpp src/share/vm/classfile/classFileParser.cpp src/share/vm/classfile/classFileParser.hpp src/share/vm/classfile/classLoader.cpp src/share/vm/classfile/classLoader.hpp src/share/vm/classfile/classLoaderData.cpp src/share/vm/classfile/classLoaderData.hpp src/share/vm/classfile/classLoaderExt.hpp src/share/vm/classfile/javaClasses.cpp src/share/vm/classfile/javaClasses.hpp src/share/vm/classfile/javaClasses.inline.hpp src/share/vm/classfile/jimage.hpp src/share/vm/classfile/klassFactory.cpp src/share/vm/classfile/moduleEntry.cpp src/share/vm/classfile/moduleEntry.hpp src/share/vm/classfile/modules.cpp src/share/vm/classfile/modules.hpp src/share/vm/classfile/packageEntry.cpp src/share/vm/classfile/packageEntry.hpp src/share/vm/classfile/sharedPathsMiscInfo.cpp src/share/vm/classfile/systemDictionary.cpp src/share/vm/classfile/systemDictionary.hpp src/share/vm/classfile/systemDictionaryShared.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/filemap.cpp src/share/vm/memory/filemap.hpp src/share/vm/memory/metaspaceShared.cpp src/share/vm/memory/metaspaceShared.hpp src/share/vm/memory/universe.cpp src/share/vm/memory/universe.hpp src/share/vm/oops/arrayKlass.cpp src/share/vm/oops/arrayKlass.hpp src/share/vm/oops/instanceKlass.cpp src/share/vm/oops/instanceKlass.hpp src/share/vm/oops/klass.cpp src/share/vm/oops/method.cpp src/share/vm/oops/objArrayKlass.cpp src/share/vm/oops/typeArrayKlass.cpp src/share/vm/opto/library_call.cpp src/share/vm/precompiled/precompiled.hpp src/share/vm/prims/jni.cpp src/share/vm/prims/jni.h src/share/vm/prims/jniCheck.cpp src/share/vm/prims/jvm.cpp src/share/vm/prims/jvm.h src/share/vm/prims/jvmti.xml src/share/vm/prims/jvmti.xsl src/share/vm/prims/jvmtiEnter.xsl src/share/vm/prims/jvmtiEnv.cpp src/share/vm/prims/jvmtiEnvBase.cpp src/share/vm/prims/jvmtiEnvBase.hpp src/share/vm/prims/jvmtiEventController.cpp src/share/vm/prims/jvmtiExport.cpp src/share/vm/prims/jvmtiExport.hpp src/share/vm/prims/jvmtiH.xsl src/share/vm/prims/jvmtiLib.xsl src/share/vm/prims/jvmtiManageCapabilities.cpp src/share/vm/prims/methodHandles.cpp src/share/vm/prims/nativeLookup.cpp src/share/vm/prims/whitebox.cpp src/share/vm/runtime/arguments.cpp src/share/vm/runtime/arguments.hpp src/share/vm/runtime/frame.cpp src/share/vm/runtime/jniHandles.cpp src/share/vm/runtime/jniHandles.hpp src/share/vm/runtime/mutexLocker.cpp src/share/vm/runtime/mutexLocker.hpp src/share/vm/runtime/os.cpp src/share/vm/runtime/os.hpp src/share/vm/runtime/reflection.cpp src/share/vm/runtime/reflection.hpp src/share/vm/runtime/sharedRuntime.cpp src/share/vm/runtime/sharedRuntime.hpp src/share/vm/runtime/statSampler.cpp src/share/vm/runtime/thread.cpp src/share/vm/services/jmm.h src/share/vm/services/management.cpp src/share/vm/trace/traceBackend.cpp src/share/vm/trace/traceDataTypes.hpp src/share/vm/trace/traceMacros.hpp src/share/vm/trace/tracetypes.xml src/share/vm/utilities/dtrace_disabled.hpp src/share/vm/utilities/ostream.cpp src/share/vm/utilities/utf8.cpp src/share/vm/utilities/utf8.hpp test/TEST.ROOT test/compiler/dependencies/MonomorphicObjectCall/TestMonomorphicObjectCall.java test/compiler/jsr292/CallSiteDepContextTest.java test/compiler/jsr292/NonInlinedCall/Agent.java test/compiler/jsr292/NonInlinedCall/GCTest.java test/compiler/jsr292/NonInlinedCall/InvokeTest.java test/compiler/jsr292/NonInlinedCall/NonInlinedReinvoker.java test/compiler/jsr292/NonInlinedCall/RedefineTest.java test/compiler/jsr292/patches/java.base/java/lang/invoke/MethodHandleHelper.java test/compiler/jvmci/SecurityRestrictionsTest.java test/compiler/jvmci/code/DataPatchTest.java test/compiler/jvmci/code/SimpleCodeInstallationTest.java test/compiler/jvmci/code/SimpleDebugInfoTest.java test/compiler/jvmci/code/VirtualObjectDebugInfoTest.java test/compiler/jvmci/common/CTVMUtilities.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/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/MetaAccessWrapper.java test/compiler/jvmci/common/patches/jdk.vm.ci/jdk/vm/ci/hotspot/PublicMetaspaceWrapperObject.java test/compiler/jvmci/compilerToVM/AllocateCompileIdTest.java test/compiler/jvmci/compilerToVM/CanInlineMethodTest.java test/compiler/jvmci/compilerToVM/CollectCountersTest.java test/compiler/jvmci/compilerToVM/DebugOutputTest.java test/compiler/jvmci/compilerToVM/DisassembleCodeBlobTest.java test/compiler/jvmci/compilerToVM/DoNotInlineOrCompileTest.java test/compiler/jvmci/compilerToVM/ExecuteInstalledCodeTest.java test/compiler/jvmci/compilerToVM/FindUniqueConcreteMethodTest.java test/compiler/jvmci/compilerToVM/GetBytecodeTest.java test/compiler/jvmci/compilerToVM/GetClassInitializerTest.java test/compiler/jvmci/compilerToVM/GetConstantPoolTest.java test/compiler/jvmci/compilerToVM/GetExceptionTableTest.java test/compiler/jvmci/compilerToVM/GetImplementorTest.java test/compiler/jvmci/compilerToVM/GetLineNumberTableTest.java test/compiler/jvmci/compilerToVM/GetLocalVariableTableTest.java test/compiler/jvmci/compilerToVM/GetMaxCallTargetOffsetTest.java test/compiler/jvmci/compilerToVM/GetNextStackFrameTest.java test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodAtSlotTest.java test/compiler/jvmci/compilerToVM/GetResolvedJavaMethodTest.java test/compiler/jvmci/compilerToVM/GetResolvedJavaTypeTest.java test/compiler/jvmci/compilerToVM/GetStackTraceElementTest.java test/compiler/jvmci/compilerToVM/GetSymbolTest.java test/compiler/jvmci/compilerToVM/GetVtableIndexForInterfaceTest.java test/compiler/jvmci/compilerToVM/HasCompiledCodeForOSRTest.java test/compiler/jvmci/compilerToVM/HasFinalizableSubclassTest.java test/compiler/jvmci/compilerToVM/InitializeConfigurationTest.java test/compiler/jvmci/compilerToVM/InvalidateInstalledCodeTest.java test/compiler/jvmci/compilerToVM/IsMatureTest.java test/compiler/jvmci/compilerToVM/LookupKlassInPoolTest.java test/compiler/jvmci/compilerToVM/LookupKlassRefIndexInPoolTest.java test/compiler/jvmci/compilerToVM/LookupMethodInPoolTest.java test/compiler/jvmci/compilerToVM/LookupNameAndTypeRefIndexInPoolTest.java test/compiler/jvmci/compilerToVM/LookupNameInPoolTest.java test/compiler/jvmci/compilerToVM/LookupSignatureInPoolTest.java test/compiler/jvmci/compilerToVM/LookupTypeTest.java test/compiler/jvmci/compilerToVM/MaterializeVirtualObjectTest.java test/compiler/jvmci/compilerToVM/MethodIsIgnoredBySecurityStackWalkTest.java test/compiler/jvmci/compilerToVM/ReadUncompressedOopTest.java test/compiler/jvmci/compilerToVM/ReprofileTest.java test/compiler/jvmci/compilerToVM/ResolveConstantInPoolTest.java test/compiler/jvmci/compilerToVM/ResolveFieldInPoolTest.java test/compiler/jvmci/compilerToVM/ResolveMethodTest.java test/compiler/jvmci/compilerToVM/ResolvePossiblyCachedConstantInPoolTest.java test/compiler/jvmci/compilerToVM/ResolveTypeInPoolTest.java test/compiler/jvmci/compilerToVM/ShouldDebugNonSafepointsTest.java test/compiler/jvmci/compilerToVM/ShouldInlineMethodTest.java test/compiler/jvmci/events/JvmciCreateMetaAccessContextTest.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/ConstantTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/RedefineClassTest.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestConstantReflectionProvider.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaField.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaMethod.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestJavaType.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestMetaAccessProvider.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaField.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaMethod.java test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/TestResolvedJavaType.java test/compiler/stable/StableConfiguration.java test/compiler/stable/TestStableBoolean.java test/compiler/stable/TestStableByte.java test/compiler/stable/TestStableChar.java test/compiler/stable/TestStableDouble.java test/compiler/stable/TestStableFloat.java test/compiler/stable/TestStableInt.java test/compiler/stable/TestStableLong.java test/compiler/stable/TestStableMemoryBarrier.java test/compiler/stable/TestStableObject.java test/compiler/stable/TestStableShort.java test/compiler/unsafe/UnsafeGetConstantField.java test/gc/TestSmallHeap.java test/gc/metaspace/PerfCounter.java test/gc/metaspace/PerfCounters.java test/runtime/BadObjectClass/BootstrapRedefine.java test/runtime/BadObjectClass/Object.java test/runtime/BootClassAppendProp/BootClassPathAppend.java test/runtime/BootClassAppendProp/BootClassPathAppendProp.java test/runtime/BootClassAppendProp/SunBootClassPath.java test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java test/runtime/CommandLine/OptionsValidation/TestOptionsWithRangesDynamic.java test/runtime/SharedArchiveFile/BasicJarBuilder.java test/runtime/SharedArchiveFile/BootAppendTests.java test/runtime/SharedArchiveFile/LoadClass.java test/runtime/SharedArchiveFile/PrintSharedArchiveAndExit.java test/runtime/SharedArchiveFile/SharedStrings.java test/runtime/SharedArchiveFile/javax/sound/sampled/MyClass.jasm test/runtime/SharedArchiveFile/nonjdk/myPackage/MyClass.java test/runtime/SharedArchiveFile/org/omg/CORBA/Context.jasm test/runtime/getSysPackage/GetSysPkgTest.java test/runtime/logging/ModulesTest.java test/runtime/modules/AccModuleTest.java test/runtime/modules/AccessCheck/CheckRead.java test/runtime/modules/AccessCheck/DiffCL_CheckRead.java test/runtime/modules/AccessCheck/DiffCL_ExpQualOther.java test/runtime/modules/AccessCheck/DiffCL_ExpQualToM1.java test/runtime/modules/AccessCheck/DiffCL_ExpUnqual.java test/runtime/modules/AccessCheck/DiffCL_PkgNotExp.java test/runtime/modules/AccessCheck/DiffCL_Umod.java test/runtime/modules/AccessCheck/DiffCL_UmodUpkg.java test/runtime/modules/AccessCheck/ExpQualOther.java test/runtime/modules/AccessCheck/ExpQualToM1.java test/runtime/modules/AccessCheck/ExpUnqual.java test/runtime/modules/AccessCheck/ExportAllUnnamed.java test/runtime/modules/AccessCheck/ModuleLibrary.java test/runtime/modules/AccessCheck/PkgNotExp.java test/runtime/modules/AccessCheck/Umod.java test/runtime/modules/AccessCheck/UmodDiffCL_ExpQualOther.java test/runtime/modules/AccessCheck/UmodDiffCL_ExpUnqual.java test/runtime/modules/AccessCheck/UmodDiffCL_PkgNotExp.java test/runtime/modules/AccessCheck/UmodDiffCL_Umod.java test/runtime/modules/AccessCheck/UmodDiffCL_UmodUpkg.java test/runtime/modules/AccessCheck/UmodUPkg.java test/runtime/modules/AccessCheck/UmodUpkgDiffCL_ExpQualOther.java test/runtime/modules/AccessCheck/UmodUpkgDiffCL_NotExp.java test/runtime/modules/AccessCheck/UmodUpkgDiffCL_Umod.java test/runtime/modules/AccessCheck/UmodUpkg_ExpQualOther.java test/runtime/modules/AccessCheck/UmodUpkg_NotExp.java test/runtime/modules/AccessCheck/UmodUpkg_Umod.java test/runtime/modules/AccessCheck/Umod_ExpQualOther.java test/runtime/modules/AccessCheck/Umod_ExpUnqual.java test/runtime/modules/AccessCheck/Umod_PkgNotExp.java test/runtime/modules/AccessCheck/Umod_UmodUpkg.java test/runtime/modules/AccessCheck/c4.java test/runtime/modules/AccessCheck/c5.java test/runtime/modules/AccessCheck/myloaders/MyDiffClassLoader.java test/runtime/modules/AccessCheck/myloaders/MySameClassLoader.java test/runtime/modules/AccessCheck/p1/c1.java test/runtime/modules/AccessCheck/p1/c1Loose.java test/runtime/modules/AccessCheck/p1/c1ReadEdge.java test/runtime/modules/AccessCheck/p1/c1ReadEdgeDiffLoader.java test/runtime/modules/AccessCheck/p2/c2.java test/runtime/modules/AccessCheck/p3/c3.jcod test/runtime/modules/AccessCheck/p3/c3ReadEdge.jcod test/runtime/modules/AccessCheck/p3/c3ReadEdgeDiffLoader.jcod test/runtime/modules/AccessCheck/p6/c6.java test/runtime/modules/AccessCheckAllUnnamed.java test/runtime/modules/AccessCheckExp.java test/runtime/modules/AccessCheckJavaBase.java test/runtime/modules/AccessCheckRead.java test/runtime/modules/AccessCheckSuper.java test/runtime/modules/AccessCheckUnnamed.java test/runtime/modules/AccessCheckWorks.java test/runtime/modules/CCE_module_msg.java test/runtime/modules/ExportTwice.java test/runtime/modules/JVMAddModuleExportToAllUnnamed.java test/runtime/modules/JVMAddModuleExports.java test/runtime/modules/JVMAddModuleExportsToAll.java test/runtime/modules/JVMAddModulePackage.java test/runtime/modules/JVMAddReadsModule.java test/runtime/modules/JVMCanReadModule.java test/runtime/modules/JVMDefineModule.java test/runtime/modules/JVMGetModuleByPkgName.java test/runtime/modules/JVMIsExportedToModule.java test/runtime/modules/LoadUnloadModuleStress.java test/runtime/modules/ModuleHelper.java test/runtime/modules/Visibility/XbootcpNoVisibility.java test/runtime/modules/Visibility/XbootcpVisibility.java test/runtime/modules/Visibility/XpatchVisibility.java test/runtime/modules/Xpatch/Xpatch2Dirs.java test/runtime/modules/Xpatch/Xpatch2DirsMain.java test/runtime/modules/Xpatch/XpatchMain.java test/runtime/modules/Xpatch/XpatchTest.java test/runtime/modules/Xpatch/XpatchTraceCL.java test/runtime/modules/XpatchCDS.java test/runtime/modules/acc_module.jcod test/runtime/modules/getModuleJNI/GetModule.java test/runtime/modules/getModuleJNI/libGetModule.c test/runtime/modules/java.base/java/lang/reflect/ModuleHelper.java test/runtime/modules/p1/c1.java test/runtime/modules/p2/c2.java test/runtime/modules/p3/c3.java test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java test/testlibrary/ClassFileInstaller.java test/testlibrary/jdk/test/lib/InMemoryJavaCompiler.java test/testlibrary/jdk/test/lib/PerfCounter.java test/testlibrary/jdk/test/lib/PerfCounters.java test/testlibrary/jdk/test/lib/cli/CommandLineOptionTest.java test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
diffstat 304 files changed, 16411 insertions(+), 2865 deletions(-) [+]
line wrap: on
line diff
--- a/make/share/makefiles/mapfile-vers	Tue Mar 15 13:48:21 2016 -0700
+++ b/make/share/makefiles/mapfile-vers	Thu Mar 17 19:04:01 2016 +0000
@@ -168,3 +168,15 @@
                 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;
+                JVM_GetModuleByPackageName;
--- a/make/test/JtregNative.gmk	Tue Mar 15 13:48:21 2016 -0700
+++ b/make/test/JtregNative.gmk	Thu Mar 17 19:04:01 2016 +0000
@@ -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 Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,49 @@
+/*
+ * 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.jcmd;
+    requires jdk.jdi;
+
+    // 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;
+
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.JStack;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.JInfo;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.ClassLoaderStats;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.FinalizerInfo;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.HeapDumper;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.HeapSummary;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.ObjectHistogram;
+    provides jdk.internal.vm.agent.spi.ToolProvider with sun.jvm.hotspot.tools.PMap;
+}
+
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ClassLoaderStats.java	Thu Mar 17 19:04:01 2016 +0000
@@ -31,14 +31,14 @@
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
-import sun.jvm.hotspot.tools.*;
 import sun.jvm.hotspot.utilities.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
 /**
   A command line tool to print class loader statistics.
 */
 
-public class ClassLoaderStats extends Tool {
+public class ClassLoaderStats extends Tool implements ToolProvider {
    boolean verbose = true;
 
    public ClassLoaderStats() {
@@ -49,6 +49,16 @@
       super(d);
    }
 
+   @Override
+   public String getName() {
+      return "classLoaderStats";
+   }
+
+   @Override
+   public void run(String... arguments) {
+      execute(arguments);
+   }
+
    public static void main(String[] args) {
       ClassLoaderStats cls = new ClassLoaderStats();
       cls.execute(args);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/FinalizerInfo.java	Thu Mar 17 19:04:01 2016 +0000
@@ -25,24 +25,21 @@
 package sun.jvm.hotspot.tools;
 
 import sun.jvm.hotspot.debugger.JVMDebugger;
-import sun.jvm.hotspot.tools.*;
 
 import sun.jvm.hotspot.oops.*;
-import sun.jvm.hotspot.runtime.VM;
 import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
-import sun.jvm.hotspot.utilities.ObjectReader;
-import sun.jvm.hotspot.utilities.MarkBits;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-import java.util.HashMap;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 
 /*
  * Iterates over the queue of object pending finalization and prints a
  * summary of these objects in the form of a histogram.
  */
-public class FinalizerInfo extends Tool {
+public class FinalizerInfo extends Tool implements ToolProvider {
 
     public FinalizerInfo() {
         super();
@@ -52,6 +49,16 @@
         super(d);
     }
 
+    @Override
+    public String getName() {
+        return "finalizerInfo";
+    }
+
+    @Override
+    public void run(String... arguments) {
+        execute(arguments);
+    }
+
     public static void main(String[] args) {
         FinalizerInfo finfo = new FinalizerInfo();
         finfo.execute(args);
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapDumper.java	Thu Mar 17 19:04:01 2016 +0000
@@ -26,6 +26,8 @@
 
 import sun.jvm.hotspot.utilities.HeapHprofBinWriter;
 import sun.jvm.hotspot.debugger.JVMDebugger;
+import jdk.internal.vm.agent.spi.ToolProvider;
+
 import java.io.IOException;
 
 /*
@@ -33,12 +35,16 @@
  * process/core as a HPROF binary file. It can also be used as a standalone
  * tool if required.
  */
-public class HeapDumper extends Tool {
+public class HeapDumper extends Tool implements ToolProvider {
 
     private static String DEFAULT_DUMP_FILE = "heap.bin";
 
     private String dumpFile;
 
+    public HeapDumper() {
+        this.dumpFile = DEFAULT_DUMP_FILE;
+    }
+
     public HeapDumper(String dumpFile) {
         this.dumpFile = dumpFile;
     }
@@ -48,6 +54,11 @@
         this.dumpFile = dumpFile;
     }
 
+    @Override
+    public String getName() {
+        return "heapDumper";
+    }
+
     protected void printFlagsUsage() {
         System.out.println("    <no option>\tto dump heap to " +
             DEFAULT_DUMP_FILE);
@@ -69,18 +80,22 @@
     // JDK jmap utility will always invoke this tool as:
     //   HeapDumper -f <file> <args...>
     public static void main(String args[]) {
-        String file = DEFAULT_DUMP_FILE;
+        HeapDumper dumper = new HeapDumper();
+        dumper.run(args);
+    }
+
+    @Override
+    public void run(String... args) {
         if (args.length > 2) {
             if (args[0].equals("-f")) {
-                file = args[1];
+                this.dumpFile = args[1];
                 String[] newargs = new String[args.length-2];
                 System.arraycopy(args, 2, newargs, 0, args.length-2);
                 args = newargs;
             }
         }
 
-        HeapDumper dumper = new HeapDumper(file);
-        dumper.execute(args);
+        execute(args);
     }
 
 }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/HeapSummary.java	Thu Mar 17 19:04:01 2016 +0000
@@ -33,8 +33,9 @@
 import sun.jvm.hotspot.memory.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class HeapSummary extends Tool {
+public class HeapSummary extends Tool implements ToolProvider {
 
    public HeapSummary() {
       super();
@@ -49,6 +50,16 @@
       hs.execute(args);
    }
 
+   @Override
+   public String getName() {
+      return "heapSummary";
+   }
+
+   @Override
+   public void run(String... arguments) {
+      execute(arguments);
+   }
+
    public void run() {
       CollectedHeap heap = VM.getVM().getUniverse().heap();
       VM.Flag[] flags = VM.getVM().getCommandLineFlags();
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JInfo.java	Thu Mar 17 19:04:01 2016 +0000
@@ -27,8 +27,9 @@
 import sun.jvm.hotspot.debugger.JVMDebugger;
 import sun.jvm.hotspot.runtime.Arguments;
 import sun.jvm.hotspot.runtime.VM;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class JInfo extends Tool {
+public class JInfo extends Tool implements ToolProvider {
     public JInfo() {
         super();
     }
@@ -94,13 +95,14 @@
         tool.run();
     }
 
-    public static void main(String[] args) {
+    @Override
+    public void run(String... args) {
         int mode = -1;
         switch (args.length) {
         case 1:
             if (args[0].charAt(0) == '-') {
                 // -h or -help or some invalid flag
-                new JInfo(mode).usage();
+                usage();
             } else {
                 mode = MODE_BOTH;
             }
@@ -114,7 +116,7 @@
                 mode = MODE_SYSPROPS;
             } else if (modeFlag.charAt(0) == '-') {
                 // -h or -help or some invalid flag
-                new JInfo(mode).usage();
+                usage();
             } else {
                 mode = MODE_BOTH;
             }
@@ -131,11 +133,16 @@
         }
 
         default:
-            new JInfo(mode).usage();
+            usage();
         }
 
-        JInfo jinfo = new JInfo(mode);
-        jinfo.execute(args);
+        this.mode = mode;
+        execute(args);
+    }
+
+    public static void main(String[] args) {
+        JInfo jinfo = new JInfo();
+        jinfo.run(args);
     }
 
     private void printVMFlags() {
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/JStack.java	Thu Mar 17 19:04:01 2016 +0000
@@ -25,8 +25,9 @@
 package sun.jvm.hotspot.tools;
 
 import sun.jvm.hotspot.debugger.JVMDebugger;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class JStack extends Tool {
+public class JStack extends Tool implements ToolProvider {
     public JStack(boolean mixedMode, boolean concurrentLocks) {
         this.mixedMode = mixedMode;
         this.concurrentLocks = concurrentLocks;
@@ -66,9 +67,8 @@
         tool.run();
     }
 
-    public static void main(String[] args) {
-        boolean mixedMode = false;
-        boolean concurrentLocks = false;
+    @Override
+    public void run(String... args) {
         int used = 0;
         for (int i = 0; i < args.length; i++) {
             if (args[i].equals("-m")) {
@@ -88,8 +88,12 @@
             args = newArgs;
         }
 
-        JStack jstack = new JStack(mixedMode, concurrentLocks);
-        jstack.execute(args);
+        execute(args);
+    }
+
+    public static void main(String[] args) {
+        JStack jstack = new JStack();
+        jstack.run(args);
     }
 
     private boolean mixedMode;
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/ObjectHistogram.java	Thu Mar 17 19:04:01 2016 +0000
@@ -27,11 +27,13 @@
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.oops.*;
 import sun.jvm.hotspot.runtime.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
+
 import java.io.PrintStream;
 
 /** A sample tool which uses the Serviceability Agent's APIs to obtain
     an object histogram from a remote or crashed VM. */
-public class ObjectHistogram extends Tool {
+public class ObjectHistogram extends Tool implements ToolProvider {
 
     public ObjectHistogram() {
        super();
@@ -41,6 +43,16 @@
        super(d);
     }
 
+    @Override
+    public String getName() {
+       return "objectHistogram";
+    }
+
+    @Override
+    public void run(String... arguments) {
+        execute(arguments);
+    }
+
    public void run() {
       run(System.out, System.err);
    }
--- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/tools/PMap.java	Thu Mar 17 19:04:01 2016 +0000
@@ -28,9 +28,9 @@
 import java.util.*;
 import sun.jvm.hotspot.debugger.*;
 import sun.jvm.hotspot.debugger.cdbg.*;
-import sun.jvm.hotspot.runtime.*;
+import jdk.internal.vm.agent.spi.ToolProvider;
 
-public class PMap extends Tool {
+public class PMap extends Tool implements ToolProvider {
 
    public PMap() {
        super();
@@ -40,6 +40,16 @@
        super(d);
    }
 
+   @Override
+   public String getName() {
+       return "pmap";
+   }
+
+   @Override
+   public void run(String... arguments) {
+       execute(arguments);
+   }
+
    public void run() {
       run(System.out);
    }
--- a/src/jdk.vm.ci/share/classes/META-INF/services/jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory	Tue Mar 15 13:48:21 2016 -0700
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,3 +0,0 @@
-jdk.vm.ci.hotspot.aarch64.AArch64HotSpotJVMCIBackendFactory
-jdk.vm.ci.hotspot.amd64.AMD64HotSpotJVMCIBackendFactory
-jdk.vm.ci.hotspot.sparc.SPARCHotSpotJVMCIBackendFactory
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.vm.ci/share/classes/module-info.java	Thu Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,37 @@
+/*
+ * 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.aarch64.AArch64HotSpotJVMCIBackendFactory;
+    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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/os/posix/dtrace/hotspot_jni.d	Thu Mar 17 19:04:01 2016 +0000
@@ -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_Runtime1.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/c1/c1_Runtime1.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/ci/ciEnv.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classFileParser.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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"
@@ -103,8 +104,6 @@
 
 #define JAVA_9_VERSION                    53
 
-enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
-
 void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
                                                   ConstantPool* cp,
                                                   const int length,
@@ -1965,7 +1964,7 @@
   const vmSymbols::SID sid = vmSymbols::find_sid(name);
   // Privileged code can use all annotations.  Other code silently drops some.
   const bool privileged = loader_data->is_the_null_class_loader_data() ||
-                          loader_data->is_ext_class_loader_data() ||
+                          loader_data->is_platform_class_loader_data() ||
                           loader_data->is_anonymous();
   switch (sid) {
     case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_reflect_CallerSensitive_signature): {
@@ -4358,17 +4357,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(),
+          super->external_name());
+      } else {
+        // Add additional message content.
+        Exceptions::fthrow(
+          THREAD_AND_LOCATION,
+          vmSymbols::java_lang_IllegalAccessError(),
+          "superclass access check failed: %s",
+          msg);
+      }
+    }
   }
 }
 
@@ -4380,16 +4391,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);
+      }
     }
   }
 }
@@ -4489,12 +4510,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,
@@ -4650,65 +4673,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 '/'.
@@ -4716,24 +4683,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;
     }
@@ -5192,7 +5170,7 @@
   }
 }
 
-InstanceKlass* ClassFileParser::create_instance_klass(TRAPS) {
+InstanceKlass* ClassFileParser::create_instance_klass(bool changed_by_loadhook, TRAPS) {
   if (_klass != NULL) {
     return _klass;
   }
@@ -5200,14 +5178,14 @@
   InstanceKlass* const ik =
     InstanceKlass::allocate_instance_klass(*this, CHECK_NULL);
 
-  fill_instance_klass(ik, CHECK_NULL);
+  fill_instance_klass(ik, changed_by_loadhook, CHECK_NULL);
 
   assert(_klass == ik, "invariant");
 
   return ik;
 }
 
-void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) {
+void ClassFileParser::fill_instance_klass(InstanceKlass* ik, bool changed_by_loadhook, TRAPS) {
   assert(ik != NULL, "invariant");
 
   set_klass_to_deallocate(ik);
@@ -5272,6 +5250,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(cld, CHECK);
+
   const Array<Method*>* const methods = ik->methods();
   assert(methods != NULL, "invariant");
   const int methods_len = methods->length();
@@ -5327,10 +5311,18 @@
     }
   }
 
+  // Obtain this_klass' module entry
+  ModuleEntry* module_entry = ik->module();
+  assert(module_entry != NULL, "module_entry should always be set");
+
+  // Obtain java.lang.reflect.Module
+  Handle module_handle(THREAD, JNIHandles::resolve(module_entry->module()));
+
   // 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(),
+                                 module_handle,
                                  _protection_domain,
                                  CHECK);
 
@@ -5344,6 +5336,15 @@
                                              CHECK);
   }
 
+  // Add read edges to the unnamed modules of the bootstrap and app class loaders.
+  if (changed_by_loadhook && !module_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(module_handle, THREAD);
+    }
+  }
+
   // Update the loader_data graph.
   record_defined_class_dependencies(ik, CHECK);
 
@@ -5351,11 +5352,24 @@
 
   if (!is_internal()) {
     if (log_is_enabled(Info, classload)) {
-      ik->print_loading_log(LogLevel::Info, _loader_data, _stream);
-    }
-    // No 'else' here as logging levels are not mutually exclusive
-    if (log_is_enabled(Debug, classload)) {
-      ik->print_loading_log(LogLevel::Debug, _loader_data, _stream);
+      ResourceMark rm;
+      const char* module_name = NULL;
+      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)) {
+        module_name = module_entry->name()->as_C_string();
+      }
+
+      if (log_is_enabled(Info, classload)) {
+        ik->print_loading_log(LogLevel::Info, _loader_data, module_name, _stream);
+      }
+      // No 'else' here as logging levels are not mutually exclusive
+      if (log_is_enabled(Debug, classload)) {
+        ik->print_loading_log(LogLevel::Debug, _loader_data, module_name, _stream);
+      }
     }
 
     if (log_is_enabled(Info, classresolve))  {
--- a/src/share/vm/classfile/classFileParser.hpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classFileParser.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classLoader.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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"
@@ -138,11 +141,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::_platform_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);
@@ -162,7 +168,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) {
@@ -356,15 +362,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);
@@ -409,11 +449,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) {
@@ -480,7 +520,7 @@
     _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
@@ -500,10 +540,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) {
@@ -512,10 +553,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);
@@ -616,6 +670,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;
@@ -641,9 +707,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) {
@@ -654,12 +742,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 {
@@ -760,246 +856,205 @@
   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);
+  _platform_modules_array = new (ResourceObj::C_HEAP, mtInternal)
+    GrowableArray<char*>(INITIAL_PLATFORM_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 _platform_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, "PLATFORM", 8) == 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 {
+        _platform_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
+s2 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(_platform_modules_array != NULL, "_platform_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_LOADER;
+    }
   }
-  if (pp == NULL) {
-    return NULL;
-  } else {
-    Handle p = java_lang_String::create_from_str(pp->filename(), THREAD);
-    return p();
+
+  array_size = _platform_modules_array->length();
+  for (int i = 0; i < array_size; i++) {
+    if (strcmp(module_name, _platform_modules_array->at(i)) == 0) {
+      return PLATFORM_LOADER;
+    }
   }
+
+  return APP_LOADER;
+}
+#endif
+
+s2 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_LOADER;
+  if (e->is_jrt()) {
+    int length = 0;
+    const jbyte* pkg_string = InstanceKlass::package_from_name(class_name, length);
+    if (pkg_string != NULL) {
+      ResourceMark rm;
+      TempNewSymbol 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_LOADER;
+  }
+  return loader_type;
+#endif
+  return ClassLoader::BOOT_LOADER; // 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) {
@@ -1018,7 +1073,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");
@@ -1037,24 +1092,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;
     }
   }
 
@@ -1085,32 +1170,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) {
@@ -1258,12 +1327,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
 //
@@ -1325,10 +1430,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);
@@ -1350,10 +1451,6 @@
   }
 }
 
-bool ClassPathZipEntry::is_jrt() {
-  return false;
-}
-
 void ClassLoader::compile_the_world() {
   EXCEPTION_MARK;
   HandleMark hm(THREAD);
@@ -1366,7 +1463,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classLoader.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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/vm/cds/resources/ModuleLoaderMap.dat"
+
+// Initial sizes of the following arrays are based on the generated ModuleLoaderMap.dat
+#define INITIAL_BOOT_MODULES_ARRAY_SIZE 30
+#define INITIAL_PLATFORM_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_LOADER = 1,      /* boot loader */
+    PLATFORM_LOADER  = 2, /* PlatformClassLoader */
+    APP_LOADER  = 3       /* AppClassLoader */
   };
  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 platform class loader
+  CDS_ONLY(static GrowableArray<char*>* _platform_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 s2 module_to_classloader(const char* module_name);
+  static void initialize_module_loader_map(JImageFile* jimage);
 #endif
+  static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
+                                 int classpath_index, TRAPS);
 
   static void  trace_class_path(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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classLoaderData.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -31,7 +31,7 @@
 //
 // Class loaders that implement a deterministic name resolution strategy
 // (including with respect to their delegation behavior), such as the boot, the
-// extension, and the system loaders of the JDK's built-in class loader
+// platform, and the system loaders of the JDK's built-in class loader
 // hierarchy, always produce the same linkset for a given configuration.
 //
 // ClassLoaderData carries information related to a linkset (e.g.,
@@ -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"
@@ -83,6 +85,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,
@@ -168,6 +171,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");
 
@@ -341,6 +368,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();
@@ -358,16 +425,30 @@
   // 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;
+  }
+
+  // release the metaspace
   Metaspace *m = _metaspace;
   if (m != NULL) {
     _metaspace = NULL;
-    // release the metaspace
     delete m;
-    // release the handles
-    if (_handles != NULL) {
-      JNIHandleBlock::release_block(_handles);
-      _handles = NULL;
-    }
+  }
+  // release the handles
+  if (_handles != NULL) {
+    JNIHandleBlock::release_block(_handles);
+    _handles = NULL;
   }
 
   // Clear all the JNI handles for methods
@@ -389,10 +470,10 @@
 }
 
 /**
- * Returns true if this class loader data is for the extension class loader.
+ * Returns true if this class loader data is for the platform class loader.
  */
-bool ClassLoaderData::is_ext_class_loader_data() const {
-  return SystemDictionary::is_ext_class_loader(class_loader());
+bool ClassLoaderData::is_platform_class_loader_data() const {
+  return SystemDictionary::is_platform_class_loader(class_loader());
 }
 
 Metaspace* ClassLoaderData::metaspace_non_null() {
@@ -438,6 +519,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) {
@@ -712,6 +797,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);
@@ -723,6 +842,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);
   }
 }
@@ -800,6 +920,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);
@@ -992,6 +1118,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classLoaderData.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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);
@@ -172,9 +180,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
@@ -218,6 +229,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();
@@ -256,7 +269,7 @@
   bool is_the_null_class_loader_data() const {
     return this == _the_null_class_loader_data;
   }
-  bool is_ext_class_loader_data() const;
+  bool is_platform_class_loader_data() const;
 
   // The Metaspace is created lazily so may be NULL.  This
   // method will allocate a Metaspace if needed.
@@ -293,11 +306,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/classLoaderExt.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/javaClasses.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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_module_field_list() == NULL) {
+        GrowableArray<Klass*>* list =
+          new (ResourceObj::C_HEAP, mtClass) GrowableArray<Klass*>(500, true);
+        set_fixup_module_field_list(list);
+      }
+      fixup_module_field_list()->push(k());
+    }
   } else {
     if (fixup_mirror_list() == NULL) {
       GrowableArray<Klass*>* list =
@@ -864,6 +880,10 @@
   }
 }
 
+void java_lang_Class::fixup_module_field(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_module_field_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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/javaClasses.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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_module_field_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_module_field(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_module_field_list() {
+    return _fixup_module_field_list;
+  }
+  static void set_fixup_module_field_list(GrowableArray<Klass*>* v) {
+    _fixup_module_field_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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/javaClasses.inline.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/jimage.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/klassFactory.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -103,11 +103,15 @@
   assert(loader_data != NULL, "invariant");
   assert(THREAD->is_Java_thread(), "must be a JavaThread");
 
+  bool changed_by_loadhook = false;
+
   ResourceMark rm;
   HandleMark hm;
 
   JvmtiCachedClassFileData* cached_class_file = NULL;
 
+  ClassFileStream* old_stream = stream;
+
   stream = prologue(stream,
                     name,
                     loader_data,
@@ -125,8 +129,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 Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,405 @@
+/*
+ * 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;
+
+
+void ModuleEntry::set_location(Symbol* location) {
+  if (_location != NULL) {
+    // _location symbol's refcounts are managed by ModuleEntry,
+    // must decrement the old one before updating.
+    _location->decrement_refcount();
+  }
+
+  _location = location;
+
+  if (location != NULL) {
+    location->increment_refcount();
+  }
+}
+
+void ModuleEntry::set_version(Symbol* version) {
+  if (_version != NULL) {
+    // _version symbol's refcounts are managed by ModuleEntry,
+    // must decrement the old one before updating.
+    _version->decrement_refcount();
+  }
+
+  _version = version;
+
+  if (version != NULL) {
+    version->increment_refcount();
+  }
+}
+
+// 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");
+
+  // Unnamed modules read everyone and all modules
+  // read java.base.  If either of these conditions
+  // hold, readability has been established.
+  if (!this->is_named() ||
+      (m == ModuleEntryTable::javabase_module())) {
+    return true;
+  }
+
+  MutexLocker m1(Module_lock);
+  if (!has_reads()) {
+    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 {
+  assert_locked_or_safepoint(Module_lock);
+  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 (has_reads()) {
+    // 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 (has_reads()) {
+    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 module_handle, Symbol* name,
+                                         Symbol* version, Symbol* location,
+                                         ClassLoaderData* loader_data) {
+  assert_locked_or_safepoint(Module_lock);
+  ModuleEntry* entry = (ModuleEntry*) NEW_C_HEAP_ARRAY(char, entry_size(), mtClass);
+
+  // 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 (!module_handle.is_null()) {
+    entry->set_module(loader_data->add_handle(module_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 module_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), module_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 module_handle, 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 (module_handle.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_module(boot_loader_data->add_handle(module_handle));
+  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(module_handle(), jb_module);
+}
+
+void ModuleEntryTable::patch_javabase_entries(Handle module_handle) {
+  if (module_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(), module_handle());
+  java_lang_Class::set_module(Universe::float_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::double_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::byte_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::bool_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::char_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::long_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::short_mirror(), module_handle());
+  java_lang_Class::set_module(Universe::void_mirror(), module_handle());
+
+  // Do the fixups for classes that have already been created.
+  GrowableArray <Klass*>* list = java_lang_Class::fixup_module_field_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_module_field(kh, module_handle);
+  }
+
+  delete java_lang_Class::fixup_module_field_list();
+  java_lang_Class::set_fixup_module_field_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 module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT,
+                p2i(this),
+                name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
+                p2i(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.");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/share/vm/classfile/moduleEntry.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,230 @@
+/*
+ * 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.
+//
+// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
+// data structure.
+class ModuleEntry : public HashtableEntry<Symbol*, mtClass> {
+private:
+  jobject _module;                     // 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() {
+    _module = 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            module() const        { return _module; }
+  void               set_module(jobject j) { _module = 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 module_handle, Symbol* name, Symbol* version,
+                         Symbol* location, ClassLoaderData* class_loader);
+  void add_entry(int index, ModuleEntry* new_entry);
+
+  int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
+
+  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)); }
+
+public:
+  ModuleEntryTable(int table_size);
+  ~ModuleEntryTable();
+
+  ModuleEntry* bucket(int i) {
+    return (ModuleEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
+  }
+
+  // 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 module_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);
+
+  // 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->module() != NULL)); }
+  static void finalize_javabase(Handle module_handle, Symbol* version, Symbol* location);
+  static void patch_javabase_entries(Handle module_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 Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,964 @@
+/*
+* 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(THREAD);
+  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(THREAD);
+    if (Modules::verify_package_name(package->as_C_string())) {
+      PackageEntryTable* const package_entry_table =
+        get_package_entry_table(h_loader, CHECK_NULL);
+      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);
+            }
+            log_info(classload)("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);
+
+    log_info(classload)("opened: %s", path);
+    ClassLoader::add_to_list(path);
+  }
+}
+
+bool Modules::is_package_defined(Symbol* package, Handle h_loader, TRAPS) {
+  PackageEntry* res = get_package_entry_by_name(package, h_loader, CHECK_false);
+  return res != NULL;
+}
+
+static void define_javabase_module(jobject module, jstring version,
+                                   jstring location, jobjectArray packages, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  Handle module_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(module_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(module_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(module_handle);
+}
+
+void Modules::define_module(jobject module, jstring version,
+                            jstring location, jobjectArray packages, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
+  }
+  Handle module_handle(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_subclass(module_handle->klass())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
+              "module is not a subclass of java.lang.reflect.Module");
+  }
+
+  char* module_name = get_module_name(module_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(module, version, location, packages, CHECK);
+    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(module_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(module_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(module_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(jobject module, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  if (module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(), "Null module object");
+  }
+  Handle module_handle(THREAD, JNIHandles::resolve(module));
+  if (!java_lang_reflect_Module::is_subclass(module_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(module_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(module_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_module(ClassLoaderData::the_null_class_loader_data()->add_handle(module_handle));
+  // Store pointer to the ModuleEntry in the unnamed module's java.lang.reflect.Module object.
+  java_lang_reflect_Module::set_module_entry(module_handle(), unnamed_module);
+}
+
+void Modules::add_module_exports(jobject from_module, jstring package, jobject to_module, TRAPS) {
+  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(THREAD);
+  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(jobject from_module, jstring package,
+                                           jobject to_module, TRAPS) {
+  if (to_module == NULL) {
+    THROW_MSG(vmSymbols::java_lang_NullPointerException(),
+              "to_module is null");
+  }
+  add_module_exports(from_module, package, to_module, CHECK);
+}
+
+void Modules::add_reads_module(jobject from_module, jobject to_module, TRAPS) {
+  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(THREAD);
+  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(jobject asking_module, jobject target_module, TRAPS) {
+  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(THREAD);
+  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(jobject from_module, jstring package,
+                                        jobject to_module, TRAPS) {
+  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(THREAD);
+  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(jclass clazz, TRAPS) {
+  assert(ModuleEntryTable::javabase_defined(), "Attempt to call get_module before java.base is defined");
+
+  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(THREAD);
+    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(THREAD, module);
+}
+
+
+jobject Modules::get_module_by_package_name(jobject loader, jstring package, TRAPS) {
+  ResourceMark rm(THREAD);
+  assert(ModuleEntryTable::javabase_defined(),
+         "Attempt to call get_module_from_pkg before java.base is defined");
+
+  if (NULL == package) {
+    THROW_MSG_(vmSymbols::java_lang_NullPointerException(),
+               "package is null", JNI_FALSE);
+  }
+  const char* package_str =
+    java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
+  if (NULL == package_str) {
+    THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(),
+               "Invalid package", JNI_FALSE);
+  }
+
+  Handle h_loader (THREAD, JNIHandles::resolve(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", JNI_FALSE);
+  }
+
+  if (strlen(package_str) == 0) {
+    // Return the unnamed module
+    ModuleEntryTable* module_table = get_module_entry_table(h_loader, CHECK_NULL);
+    if (NULL == module_table) return NULL;
+    const ModuleEntry* const unnamed_module = module_table->unnamed_module();
+    return JNIHandles::make_local(THREAD, JNIHandles::resolve(unnamed_module->module()));
+
+  } else {
+    TempNewSymbol package_sym = SymbolTable::new_symbol(package_str, CHECK_NULL);
+    return get_module(package_sym, h_loader, CHECK_NULL);
+  }
+  return NULL;
+}
+
+
+// This method is called by JFR and by the above method.
+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->module() != NULL) {
+    return JNIHandles::make_local(THREAD, JNIHandles::resolve(module_entry->module()));
+  }
+
+  return NULL;
+}
+
+void Modules::add_module_package(jobject module, jstring package, TRAPS) {
+  ResourceMark rm(THREAD);
+
+  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(jobject module, jstring package, TRAPS) {
+  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()) { // No-op for unnamed module.
+    PackageEntry *package_entry = get_package_entry(module_entry, package, CHECK);
+    ResourceMark rm(THREAD);
+    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 Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,151 @@
+/*
+* 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_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(jobject module, jstring version,
+                            jstring location, jobjectArray packages, TRAPS);
+
+  // 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(jobject module, TRAPS);
+
+  // 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(jobject from_module, jstring package, jobject to_module, TRAPS);
+
+  // 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(jobject from_module, jstring package, jobject to_module, TRAPS);
+
+  // 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(jobject from_module, jobject to_module, TRAPS);
+
+  // 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(jobject asking_module, jobject target_module, TRAPS);
+
+  // 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(jobject from_module, jstring package, jobject to_module, TRAPS);
+
+  // Return the java.lang.reflect.Module object for this class object.
+  static jobject get_module(jclass clazz, TRAPS);
+
+  // Return the java.lang.reflect.Module object for this class loader and package.
+  // Returns NULL if the class loader has not loaded any classes in the package.
+  // The package should contain /'s, not .'s, as in java/lang, not java.lang.
+  // NullPointerException is thrown if package is null.
+  // IllegalArgumentException is thrown if loader is neither null nor a subtype of
+  // java/lang/ClassLoader.
+  static jobject get_module_by_package_name(jobject loader, jstring package, TRAPS);
+
+  // 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(jobject module, jstring package, TRAPS);
+
+  // 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(jobject module, jstring package, TRAPS);
+
+  // 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 Mar 17 19:04:01 2016 +0000
@@ -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_ARRAY(char, entry_size(), mtClass);
+
+  // 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 Mar 17 19:04:01 2016 +0000
@@ -0,0 +1,202 @@
+/*
+ * 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
+//
+// The Mutex Module_lock is shared between ModuleEntry and PackageEntry, to lock either
+// data structure.
+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);
+
+  int entry_size() const { return BasicHashtable<mtClass>::entry_size(); }
+
+  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)); }
+
+public:
+  PackageEntryTable(int table_size);
+  ~PackageEntryTable();
+
+  PackageEntry* bucket(int i) {
+    return (PackageEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
+  }
+
+  // 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);
+
+  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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/sharedPathsMiscInfo.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -77,7 +77,7 @@
   outputStream* out = LogHandle(classpath)::info_stream();
   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);
@@ -126,7 +126,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 =", Arguments::get_sysclasspath());
     }
     break;
   case NON_EXIST: // fall-through
--- a/src/share/vm/classfile/systemDictionary.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/systemDictionary.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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"
@@ -171,13 +173,13 @@
 }
 
 /**
- * Returns true if the passed class loader is the extension class loader.
+ * Returns true if the passed class loader is the platform class loader.
  */
-bool SystemDictionary::is_ext_class_loader(Handle class_loader) {
+bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
   if (class_loader.is_null()) {
     return false;
   }
-  return (class_loader->klass()->name() == vmSymbols::sun_misc_Launcher_ExtClassLoader());
+  return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass());
 }
 
 // ----------------------------------------------------------------------------
@@ -1144,6 +1146,7 @@
   const char* pkg = "java/";
   if (!HAS_PENDING_EXCEPTION &&
       !class_loader.is_null() &&
+      !SystemDictionary::is_platform_class_loader(class_loader) &&
       parsed_name != NULL &&
       !strncmp((const char*)parsed_name->bytes(), pkg, strlen(pkg))) {
     // It is illegal to define classes in the "java." package from
@@ -1236,13 +1239,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 = 0;
+  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 +1328,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).
@@ -1303,12 +1387,20 @@
     }
 
     if (log_is_enabled(Info, classload)) {
-      ik()->print_loading_log(LogLevel::Info, loader_data, NULL);
+      ik()->print_loading_log(LogLevel::Info, loader_data, NULL, NULL);
     }
     // No 'else' here as logging levels are not mutually exclusive
 
     if (log_is_enabled(Debug, classload)) {
-      ik()->print_loading_log(LogLevel::Debug, loader_data, NULL);
+      ik()->print_loading_log(LogLevel::Debug, loader_data, NULL, NULL);
+    }
+
+    // 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()) {
@@ -1329,7 +1421,68 @@
 
 instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
   instanceKlassHandle nh = instanceKlassHandle(); // null Handle
+
   if (class_loader.is_null()) {
+    int length = 0;
+    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) {
+      TempNewSymbol 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.
@@ -1344,7 +1497,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
@@ -1669,7 +1822,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();
 }
@@ -1940,6 +2093,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/systemDictionary.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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_loader_ClassLoaders_AppClassLoader_klass,      jdk_internal_loader_ClassLoaders_AppClassLoader,       Pre ) \
+  do_klass(jdk_internal_loader_ClassLoaders_PlatformClassLoader_klass, jdk_internal_loader_ClassLoaders_PlatformClassLoader,  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,
@@ -653,7 +658,7 @@
   static instanceKlassHandle load_shared_class(Symbol* class_name,
                                                Handle class_loader,
                                                TRAPS);
-  static bool is_ext_class_loader(Handle class_loader);
+  static bool is_platform_class_loader(Handle class_loader);
 
 protected:
   static Klass* find_shared_class(Symbol* class_name);
--- a/src/share/vm/classfile/systemDictionaryShared.hpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/systemDictionaryShared.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/classfile/vmSymbols.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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(jdk_internal_misc_Signal,                  "jdk/internal/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_loader_ClassLoaders_AppClassLoader,      "jdk/internal/loader/ClassLoaders$AppClassLoader")      \
+  template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \
                                                                                                   \
   /* Java runtime version access */                                                               \
   template(java_lang_VersionProps,                    "java/lang/VersionProps")                   \
   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,22 @@
   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(addReads_name,                             "addReads")                                 \
+  template(addReads_signature,                        "(Ljava/lang/reflect/Module;Ljava/lang/reflect/Module;)V")           \
   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 +548,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 +568,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 +593,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 +654,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 +1088,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/interpreter/bytecodeInterpreter.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/interpreter/linkResolver.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/jvmci/jvmciEnv.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/logging/logTag.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -62,6 +62,7 @@
   LOG_TAG(logging) \
   LOG_TAG(marking) \
   LOG_TAG(metaspace) \
+  LOG_TAG(modules) \
   LOG_TAG(monitorinflation) \
   LOG_TAG(os) \
   LOG_TAG(phases) \
--- a/src/share/vm/memory/filemap.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/memory/filemap.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -226,12 +226,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;
           }
         }
@@ -282,7 +291,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;
@@ -291,7 +300,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);
         }
       }
@@ -871,6 +880,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/memory/filemap.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/memory/metaspaceShared.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -603,14 +603,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);
@@ -716,8 +709,7 @@
 }
 
 
-void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) {
-  Klass* k = obj;
+void MetaspaceShared::link_one_shared_class(Klass* k, TRAPS) {
   if (k->is_instance_klass()) {
     InstanceKlass* ik = InstanceKlass::cast(k);
     // Link the class to cause the bytecodes to be rewritten and the
@@ -734,6 +726,16 @@
   }
 }
 
+void MetaspaceShared::check_shared_class_loader_type(Klass* k) {
+  if (k->is_instance_klass()) {
+    InstanceKlass* ik = InstanceKlass::cast(k);
+    u2 loader_type = ik->loader_type();
+    ResourceMark rm;
+    guarantee(loader_type != 0,
+              "Class loader type is not set for this class %s", ik->name()->as_C_string());
+  }
+}
+
 void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
   // We need to iterate because verification may cause additional classes
   // to be loaded.
@@ -765,6 +767,7 @@
 }
 
 void MetaspaceShared::prepare_for_dumping() {
+  Arguments::check_unsupported_dumping_properties();
   ClassLoader::initialize_shared_path();
   FileMapInfo::allocate_classpath_entry_table();
 }
@@ -901,7 +904,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
@@ -1089,36 +1092,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/memory/metaspaceShared.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/memory/universe.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -155,6 +155,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;
@@ -667,7 +668,6 @@
   } else {
     SymbolTable::create_table();
     StringTable::create_table();
-    ClassLoader::create_package_info_table();
 
     if (DumpSharedSpaces) {
       MetaspaceShared::prepare_for_dumping();
@@ -886,6 +886,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/memory/universe.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/arrayKlass.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -95,11 +95,18 @@
 
 // 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 = (module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL;
+  java_lang_Class::create_mirror(k, Handle(THREAD, k->class_loader()), Handle(THREAD, module), Handle(NULL), CHECK);
 }
 
 GrowableArray<Klass*>* ArrayKlass::compute_secondary_supers(int num_extra_slots) {
--- a/src/share/vm/oops/arrayKlass.hpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/arrayKlass.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -113,7 +113,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/instanceKlass.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -1972,8 +1972,9 @@
 }
 
 void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
+  instanceKlassHandle ik(THREAD, this);
+  ik->set_package(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();
@@ -2178,26 +2179,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(ClassLoaderData* loader_data, TRAPS) {
+  int length = 0;
+  const jbyte* base_name = package_from_name(name(), length);
+
+  if (base_name != NULL && loader_data != NULL) {
+    TempNewSymbol pkg_name = SymbolTable::new_symbol((const char*)base_name, length, CHECK);
+
+    // Find in class loader's package entry table.
+    _package_entry = loader_data->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_data->packages()->lookup(pkg_name, ModuleEntryTable::javabase_module());
+      } else {
+        assert(loader_data->modules()->unnamed_module() != NULL, "unnamed module is NULL");
+        _package_entry = loader_data->packages()->lookup(pkg_name,
+                                                         loader_data->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_data->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_data->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_data != NULL) ? loader_data->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,
@@ -2225,43 +2335,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 = 0;
+    int length2 = 0;
+    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);
   }
 }
 
@@ -2300,7 +2391,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(class2))
     return false;
 
   // As long as there is an outer1.getEnclosingClass,
@@ -2908,6 +2999,7 @@
 
 void InstanceKlass::print_loading_log(LogLevel::type type,
                                       ClassLoaderData* loader_data,
+                                      const char* module_name,
                                       const ClassFileStream* cfs) const {
   ResourceMark rm;
   outputStream* log;
@@ -2928,7 +3020,11 @@
   // Source
   if (cfs != NULL) {
     if (cfs->source() != NULL) {
-      log->print(" source: %s", cfs->source());
+      if (module_name != NULL) {
+        log->print(" source: jrt:/%s", module_name);
+      } else {
+        log->print(" source: %s", cfs->source());
+      }
     } else if (loader_data == ClassLoaderData::the_null_class_loader_data()) {
       Thread* THREAD = Thread::current();
       Klass* caller =
--- a/src/share/vm/oops/instanceKlass.hpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/instanceKlass.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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 "logging/logLevel.hpp"
 #include "memory/referenceType.hpp"
 #include "oops/annotations.hpp"
@@ -140,6 +143,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.
@@ -199,16 +204,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_platform_class = 1 << 12, // defining class loader is platform 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_platform_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_platform_class() const {
+    return (_misc_flags & _misc_is_shared_platform_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_LOADER:
+      _misc_flags |= _misc_is_shared_boot_class;
+       break;
+    case ClassLoader::PLATFORM_LOADER:
+      _misc_flags |= _misc_is_shared_platform_class;
+      break;
+    case ClassLoader::APP_LOADER:
+      _misc_flags |= _misc_is_shared_app_class;
+      break;
+    default:
+      ShouldNotReachHere();
+      break;
+    }
+  }
+
   bool has_nonstatic_fields() const        {
     return (_misc_flags & _misc_has_nonstatic_fields) != 0;
   }
@@ -395,6 +439,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(ClassLoaderData* loader_data, 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,
@@ -1030,6 +1079,7 @@
 
   // Naming
   const char* signature_name() const;
+  static const jbyte* package_from_name(const Symbol* name, int& length);
 
   // GC specific object visitors
   //
@@ -1247,7 +1297,8 @@
   void oop_verify_on(oop obj, outputStream* st);
 
   // Logging
-  void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data, const ClassFileStream* cfs) const;
+  void print_loading_log(LogLevel::type type, ClassLoaderData* loader_data,
+                         const char* module_name, const ClassFileStream* cfs) const;
 };
 
 // for adding methods
--- a/src/share/vm/oops/klass.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/klass.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -512,7 +512,21 @@
   // 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 java.lang.reflect.Module, if available
+    Handle module_handle(THREAD, ((module_entry != NULL) ? JNIHandles::resolve(module_entry->module()) : (oop)NULL));
+    java_lang_Class::create_mirror(this, loader, module_handle, protection_domain, CHECK);
   }
 }
 
--- a/src/share/vm/oops/method.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/method.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -1329,7 +1329,7 @@
   // exception: the AES intrinsics come from lib/ext/sunjce_provider.jar
   // which does not use the class default class loader so we check for its loader here
   const InstanceKlass* ik = InstanceKlass::cast(holder);
-  if ((ik->class_loader() != NULL) && !SystemDictionary::is_ext_class_loader(ik->class_loader())) {
+  if ((ik->class_loader() != NULL) && !SystemDictionary::is_platform_class_loader(ik->class_loader())) {
     return vmSymbols::NO_SID;   // regardless of name, no intrinsics here
   }
 
--- a/src/share/vm/oops/objArrayKlass.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/objArrayKlass.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/oops/typeArrayKlass.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/opto/library_call.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -319,8 +319,6 @@
 
   bool inline_profileBoolean();
   bool inline_isCompileConstant();
-
-  bool inline_deoptimize();
 };
 
 //---------------------------make_vm_intrinsic----------------------------
@@ -821,9 +819,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.
@@ -6754,12 +6749,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/precompiled/precompiled.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jni.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -28,7 +28,9 @@
 #include "classfile/altHashing.hpp"
 #include "classfile/classFileStream.hpp"
 #include "classfile/classLoader.hpp"
+#include "classfile/javaClasses.hpp"
 #include "classfile/javaClasses.inline.hpp"
+#include "classfile/modules.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
@@ -3443,6 +3445,47 @@
   return JNI_OK;
 JNI_END
 
+
+JNI_ENTRY(jobject, jni_GetModule(JNIEnv* env, jclass clazz))
+  JNIWrapper("GetModule");
+  return Modules::get_module(clazz, THREAD);
+JNI_END
+
+
+JNI_ENTRY(void, jni_AddModuleReads(JNIEnv* env, jobject m1, jobject m2))
+  JNIWrapper("AddModuleReads");
+  if (m1 == NULL || m2 == NULL) {
+    THROW(vmSymbols::java_lang_NullPointerException());
+  }
+  JavaValue result(T_VOID);
+  Handle m1_h(THREAD, JNIHandles::resolve(m1));
+  if (!java_lang_reflect_Module::is_instance(m1_h())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad m1 object");
+  }
+  Handle m2_h(THREAD, JNIHandles::resolve(m2));
+  if (!java_lang_reflect_Module::is_instance(m2_h())) {
+    THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Bad m2 object");
+  }
+  JavaCalls::call_static(&result,
+                         KlassHandle(THREAD, SystemDictionary::module_Modules_klass()),
+                         vmSymbols::addReads_name(),
+                         vmSymbols::addReads_signature(),
+                         m1_h,
+                         m2_h,
+                         THREAD);
+JNI_END
+
+
+JNI_ENTRY(jboolean, jni_CanReadModule(JNIEnv* env, jobject m1, jobject m2))
+  JNIWrapper("CanReadModule");
+  if (m1 == NULL || m2 == NULL) {
+    THROW_(vmSymbols::java_lang_NullPointerException(), JNI_FALSE);
+  }
+  jboolean res = Modules::can_read_module(m1, m2, CHECK_false);
+  return res;
+JNI_END
+
+
 // Structure containing all jni functions
 struct JNINativeInterface_ jni_NativeInterface = {
     NULL,
@@ -3722,7 +3765,13 @@
 
     // New 1_6 features
 
-    jni_GetObjectRefType
+    jni_GetObjectRefType,
+
+    // Module features
+
+    jni_GetModule,
+    jni_AddModuleReads,
+    jni_CanReadModule
 };
 
 
--- a/src/share/vm/prims/jni.h	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jni.h	Thu Mar 17 19:04:01 2016 +0000
@@ -765,6 +765,17 @@
 
     jobjectRefType (JNICALL *GetObjectRefType)
         (JNIEnv* env, jobject obj);
+
+    /* Module Features */
+
+    jobject (JNICALL *GetModule)
+       (JNIEnv* env, jclass clazz);
+
+    void (JNICALL *AddModuleReads)
+       (JNIEnv* env, jobject m1, jobject m2);
+
+    jboolean (JNICALL *CanReadModule)
+       (JNIEnv* env, jobject m1, jobject m2);
 };
 
 /*
@@ -1857,6 +1868,20 @@
         return functions->GetObjectRefType(this, obj);
     }
 
+    /* Module Features */
+
+    jobject GetModule(jclass clazz) {
+        return functions->GetModule(this, clazz);
+    }
+
+    void AddModuleReads(jobject fromModule, jobject sourceModule) {
+        functions->AddModuleReads(this, fromModule, sourceModule);
+    }
+
+    jboolean CanReadModule(jobject askingModule, jobject sourceModule) {
+        return functions->CanReadModule(this, askingModule, sourceModule);
+    }
+
 #endif /* __cplusplus */
 };
 
--- a/src/share/vm/prims/jniCheck.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jniCheck.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -1989,7 +1989,48 @@
     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
 
+JNI_ENTRY_CHECKED(void,
+  checked_jni_AddModuleReads(JNIEnv *env,
+                             jobject fromModule,
+                             jobject sourceModule))
+    functionEnter(thr);
+    IN_VM(
+      jniCheck::validate_object(thr, fromModule);
+      if (sourceModule != NULL) {
+        jniCheck::validate_object(thr, sourceModule);
+      }
+    )
+    UNCHECKED()->AddModuleReads(env,fromModule,sourceModule);
+    functionExit(thr);
+JNI_END
+
+JNI_ENTRY_CHECKED(jboolean,
+  checked_jni_CanReadModule(JNIEnv *env,
+                            jobject askingModule,
+                            jobject sourceModule))
+    functionEnter(thr);
+    IN_VM(
+      jniCheck::validate_object(thr, askingModule);
+      if (sourceModule != NULL) {
+        jniCheck::validate_object(thr, sourceModule);
+      }
+    )
+    jboolean result = UNCHECKED()->CanReadModule(env,askingModule,sourceModule);
+    functionExit(thr);
+    return result;
+JNI_END
 
 /*
  * Structure containing all checked jni functions
@@ -2272,7 +2313,13 @@
 
     // New 1.6 Features
 
-    checked_jni_GetObjectRefType
+    checked_jni_GetObjectRefType,
+
+    // Module Features
+
+    checked_jni_GetModule,
+    checked_jni_AddModuleReads,
+    checked_jni_CanReadModule
 };
 
 
--- a/src/share/vm/prims/jvm.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvm.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -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,58 @@
             (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(module, version, location, packages, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_SetBootLoaderUnnamedModule(JNIEnv *env, jobject module))
+  JVMWrapper("JVM_SetBootLoaderUnnamedModule");
+  Modules::set_bootloader_unnamed_module(module, CHECK);
+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(from_module, package, to_module, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExportsToAllUnnamed(JNIEnv *env, jobject from_module, jstring package))
+  JVMWrapper("JVM_AddModuleExportsToAllUnnamed");
+  Modules::add_module_exports_to_all_unnamed(from_module, package, CHECK);
+JVM_END
+
+JVM_ENTRY(void, JVM_AddModuleExportsToAll(JNIEnv *env, jobject from_module, jstring package))
+  JVMWrapper("JVM_AddModuleExportsToAll");
+  Modules::add_module_exports(from_module, package, NULL, CHECK);
+JVM_END
+
+JVM_ENTRY (void, JVM_AddReadsModule(JNIEnv *env, jobject from_module, jobject source_module))
+  JVMWrapper("JVM_AddReadsModule");
+  Modules::add_reads_module(from_module, source_module, CHECK);
+JVM_END
+
+JVM_ENTRY(jboolean, JVM_CanReadModule(JNIEnv *env, jobject asking_module, jobject source_module))
+  JVMWrapper("JVM_CanReadModule");
+  return Modules::can_read_module(asking_module, source_module, THREAD);
+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(from_module, package, to_module, THREAD);
+JVM_END
+
+JVM_ENTRY (void, JVM_AddModulePackage(JNIEnv *env, jobject module, jstring package))
+  JVMWrapper("JVM_AddModulePackage");
+  Modules::add_module_package(module, package, CHECK);
+JVM_END
+
+JVM_ENTRY (jobject, JVM_GetModuleByPackageName(JNIEnv *env, jobject loader, jstring package))
+  JVMWrapper("JVM_GetModuleByPackageName");
+  return Modules::get_module_by_package_name(loader, package, THREAD);
+JVM_END
 
 // Reflection support //////////////////////////////////////////////////////////////////////////////
 
--- a/src/share/vm/prims/jvm.h	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvm.h	Thu Mar 17 19:04:01 2016 +0000
@@ -417,6 +417,41 @@
                           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);
+
+JNIEXPORT jobject JNICALL
+JVM_GetModuleByPackageName(JNIEnv* env, jobject loader, jstring package);
+
+/*
  * Reflection support functions
  */
 
@@ -920,6 +955,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmti.xml	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -21,7 +21,7 @@
  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.
-  
+
 -->
 
 <!DOCTYPE specification [
@@ -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>
@@ -863,6 +863,23 @@
     to be instrumented by the use of wrapper methods.
   </intro>
 
+<intro id="bcimodules" label="Bytecode Instrumentation of code in modules">
+  Agents that instrument code in named modules may need to arrange for those
+  modules to read other modules. If code is instrumented to invoke a method
+  in a support class in another module, then the module of the instrumented
+  code should read the module of the supporting class. Furthermore, the
+  supporting class will only be accessible to the instrumented code if
+  it is <code>public</code> and in a package that is exported by its module.
+  Agents can use the JNI functions <code>CanReadModule</code> and
+  <code>AddModuleReads</code> to test and update a module to read another.
+  <p/>
+  As an aid to agents that deploy supporting classes on the search path of
+  the bootstrap class loader, or the search path of the class loader that
+  loads the main class, the Java virtual machine arranges for the module
+  of classes transformed by the <eventlink id="ClassFileLoadHook"/> event to
+  read the unnamed module of both class loaders.
+</intro>
+
   <intro id="mUTF" label="Modified UTF-8 String Encoding">
     <jvmti/> uses modified UTF-8 to encode character strings.
     This is the same encoding used by JNI.
@@ -1880,10 +1897,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 +6473,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 +6558,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>.
@@ -9941,6 +9988,12 @@
           See <eventlink id="ResourceExhausted"/>.
 	</description>
       </capabilityfield>
+      <capabilityfield id="can_generate_early_vmstart" since="9">
+        <description>
+          Can generate the <code>VMStart</code> event early.
+          See <eventlink id="VMStart"/>.
+        </description>
+      </capabilityfield>
     </capabilitiestypedef>
 
     <function id="GetPotentialCapabilities" jkernel="yes" phase="onload" num="140">
@@ -12351,7 +12404,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 +12420,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 +12431,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 +12478,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">
@@ -12496,9 +12545,28 @@
       The VM initialization event signals the start of the VM.
       At this time JNI is live but the VM is not yet fully initialized.
       Once this event is generated, the agent is free to call any JNI function.
-      This event signals the beginning of the start phase, 
+      This event signals the beginning of the start phase,
       <jvmti/> functions permitted in the start phase may be called.
       <p/>
+      The timing of this event may depend on whether the agent has added the
+      <internallink id="jvmtiCapabilities.can_generate_early_vmstart">
+      <code>can_generate_early_vmstart</code></internallink> capability or not.
+      If the capability has been added then the VM posts the event as early
+      as possible. The VM is capable of executing bytecode but it may not have
+      initialized to the point where it can load classes in modules other than
+      <code>java.base</code>. Agents that do load-time instrumentation in this
+      phase must take great care when instrumenting code that potentially
+      executes in this phase. Care should also be taken with JNI
+      <code>FindClass</code> as it may not be possible to load classes that are
+      not in the <code>java.base</code> module.
+      If the capability has not been added then the VM delays posting this
+      event until it is capable of loading classes in modules other than
+      <code>java.base</code> or the VM has completed its initialization.
+      Agents that create more than one JVM TI environment, where the
+      capability is added to some but not all environments, may observe the
+      start phase beginning earlier in the JVM TI environments that possess
+      the capabilty.
+      <p/>
       In the case of VM start-up failure, this event will not be sent.
     </description>
     <origin>jvmdi</origin>
@@ -12576,7 +12644,7 @@
     </parameters>
   </event>
 
-  <event label="Compiled Method Load"
+  <event label="Compiled Method Load" phase="start"
 	 id="CompiledMethodLoad" const="JVMTI_EVENT_COMPILED_METHOD_LOAD" num="68">
     <description>
       Sent when a method is compiled and loaded into memory by the VM.
@@ -12667,7 +12735,7 @@
     </parameters>
   </event>
 
-  <event label="Compiled Method Unload"
+  <event label="Compiled Method Unload" phase="start"
 	 id="CompiledMethodUnload" const="JVMTI_EVENT_COMPILED_METHOD_UNLOAD" num="69">
     <description>
       Sent when a compiled method is unloaded from memory.
@@ -14340,6 +14408,17 @@
   <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>
+  <change date="17 February 2016" version="9.0.0">
+      Support for modules:
+       - Add new capability can_generate_early_vmstart
+       - Allow CompiledMethodLoad events at start phase
+  </change>
 </changehistory>
 
 </specification>
--- a/src/share/vm/prims/jvmti.xsl	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmti.xsl	Thu Mar 17 19:04:01 2016 +0000
@@ -1,6 +1,6 @@
 <?xml version="1.0"?> 
 <!--
- Copyright (c) 2002, 2006, 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
@@ -1801,7 +1801,7 @@
             <xsl:text>) (jvmtiEnv* env</xsl:text>
             <xsl:apply-templates select="$thisFunction/parameters" mode="signature">
               <xsl:with-param name="comma">
-                <xsl:text>, &#xA;                       </xsl:text>
+                <xsl:text>,&#xA;                       </xsl:text>
               </xsl:with-param>
             </xsl:apply-templates>
             <xsl:text>);</xsl:text>
--- a/src/share/vm/prims/jvmtiEnter.xsl	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiEnter.xsl	Thu Mar 17 19:04:01 2016 +0000
@@ -1,6 +1,6 @@
 <?xml version="1.0"?> 
 <!--
- Copyright (c) 2002, 2015, 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
@@ -517,7 +517,7 @@
   }</xsl:text>
       </xsl:if>
       <xsl:if test="contains(@phase,'start')">
-        <xsl:text>  if(JvmtiEnv::get_phase()!=JVMTI_PHASE_START &amp;&amp; JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) {
+        <xsl:text>  if(JvmtiEnv::get_phase(env)!=JVMTI_PHASE_START &amp;&amp; JvmtiEnv::get_phase()!=JVMTI_PHASE_LIVE) {
 </xsl:text>
     <xsl:if test="$trace='Trace'">
       <xsl:text>    if (trace_flags) {
--- a/src/share/vm/prims/jvmtiEnv.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiEnv.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -187,6 +187,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
   //
 
@@ -563,7 +577,7 @@
 // phase_ptr - pre-checked for NULL
 jvmtiError
 JvmtiEnv::GetPhase(jvmtiPhase* phase_ptr) {
-  *phase_ptr = get_phase();
+  *phase_ptr = phase();
   return JVMTI_ERROR_NONE;
 } /* end GetPhase */
 
@@ -3489,7 +3503,7 @@
 
   for (SystemProperty* p = Arguments::system_properties(); p != NULL; p = p->next()) {
     if (strcmp(property, p->key()) == 0) {
-      if (p->set_value(value_ptr)) {
+      if (p->set_writeable_value(value_ptr)) {
         err =  JVMTI_ERROR_NONE;
       }
     }
--- a/src/share/vm/prims/jvmtiEnvBase.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiEnvBase.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -114,6 +114,17 @@
   }
 }
 
+jvmtiPhase
+JvmtiEnvBase::phase() {
+  // For the JVMTI environments possessed the can_generate_early_vmstart:
+  //   replace JVMTI_PHASE_PRIMORDIAL with JVMTI_PHASE_START
+  if (_phase == JVMTI_PHASE_PRIMORDIAL &&
+      JvmtiExport::early_vmstart_recorded() &&
+      early_vmstart_env()) {
+    return JVMTI_PHASE_START;
+  }
+  return _phase; // Normal case
+}
 
 bool
 JvmtiEnvBase::is_valid() {
@@ -1475,3 +1486,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiEnvBase.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -75,6 +75,7 @@
   };
 
   static jvmtiPhase  get_phase()                    { return _phase; }
+  static jvmtiPhase  get_phase(jvmtiEnv* env)       { return ((JvmtiEnvBase*)JvmtiEnv_from_jvmti_env(env))->phase(); }
   static void  set_phase(jvmtiPhase phase)          { _phase = phase; }
   static bool is_vm_live()                          { return _phase == JVMTI_PHASE_LIVE; }
 
@@ -140,6 +141,7 @@
 
  public:
 
+  jvmtiPhase  phase();
   bool is_valid();
 
   bool use_version_1_0_semantics();  // agent asked for version 1.0
@@ -160,6 +162,10 @@
 
   jvmtiCapabilities *get_prohibited_capabilities()  { return &_prohibited_capabilities; }
 
+  bool early_vmstart_env() {
+    return get_capabilities()->can_generate_early_vmstart != 0;
+  }
+
   static char** get_all_native_method_prefixes(int* count_ptr);
 
   // This test will answer true when all environments have been disposed and some have
@@ -689,4 +695,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->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/jvmtiEventController.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiEventController.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -98,6 +98,7 @@
 static const jlong  EARLY_EVENT_BITS = CLASS_FILE_LOAD_HOOK_BIT |
                                VM_START_BIT | VM_INIT_BIT | VM_DEATH_BIT | NATIVE_METHOD_BIND_BIT |
                                THREAD_START_BIT | THREAD_END_BIT |
+                               COMPILED_METHOD_LOAD_BIT | COMPILED_METHOD_UNLOAD_BIT |
                                DYNAMIC_CODE_GENERATED_BIT;
 static const jlong  GLOBAL_EVENT_BITS = ~THREAD_FILTERED_EVENT_BITS;
 static const jlong  SHOULD_POST_ON_EXCEPTIONS_BITS = EXCEPTION_BITS | METHOD_EXIT_BIT | FRAME_POP_BIT;
@@ -409,7 +410,7 @@
     env->env_event_enable()->_event_callback_enabled.get_bits() &
     env->env_event_enable()->_event_user_enabled.get_bits();
 
-  switch (JvmtiEnv::get_phase()) {
+  switch (env->phase()) {
   case JVMTI_PHASE_PRIMORDIAL:
   case JVMTI_PHASE_ONLOAD:
     // only these events allowed in primordial or onload phase
@@ -576,8 +577,6 @@
   // filtered events and there weren't last time
   if (    (any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) != 0 &&
       (was_any_env_thread_enabled & THREAD_FILTERED_EVENT_BITS) == 0) {
-    assert(JvmtiEnv::is_vm_live() || (JvmtiEnv::get_phase()==JVMTI_PHASE_START),
-      "thread filtered events should not be enabled when VM not in start or live phase");
     {
       MutexLocker mu(Threads_lock);   //hold the Threads_lock for the iteration
       for (JavaThread *tp = Threads::first(); tp != NULL; tp = tp->next()) {
--- a/src/share/vm/prims/jvmtiExport.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiExport.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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,
@@ -410,6 +441,11 @@
   JvmtiEnvBase::set_phase(JVMTI_PHASE_PRIMORDIAL);
 }
 
+void JvmtiExport::enter_early_start_phase() {
+  JvmtiManageCapabilities::recompute_always_capabilities();
+  set_early_vmstart_recorded(true);
+}
+
 void JvmtiExport::enter_start_phase() {
   JvmtiManageCapabilities::recompute_always_capabilities();
   JvmtiEnvBase::set_phase(JVMTI_PHASE_START);
@@ -428,6 +464,28 @@
 // and call the agent's premain() for java.lang.instrument.
 //
 
+void JvmtiExport::post_early_vm_start() {
+  EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg Early VM start event triggered" ));
+
+  // can now enable some events
+  JvmtiEventController::vm_start();
+
+  JvmtiEnvIterator it;
+  for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+    // Only early vmstart envs post early VMStart event
+    if (env->early_vmstart_env() && env->is_enabled(JVMTI_EVENT_VM_START)) {
+      EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt Early VM start event sent" ));
+      JavaThread *thread  = JavaThread::current();
+      JvmtiThreadEventMark jem(thread);
+      JvmtiJavaThreadEventTransition jet(thread);
+      jvmtiEventVMStart callback = env->callbacks()->VMStart;
+      if (callback != NULL) {
+        (*callback)(env->jvmti_external(), jem.jni_env());
+      }
+    }
+  }
+}
+
 void JvmtiExport::post_vm_start() {
   EVT_TRIG_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Trg VM start event triggered" ));
 
@@ -436,7 +494,8 @@
 
   JvmtiEnvIterator it;
   for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
-    if (env->is_enabled(JVMTI_EVENT_VM_START)) {
+    // Early vmstart envs do not post normal VMStart event
+    if (!env->early_vmstart_env() && env->is_enabled(JVMTI_EVENT_VM_START)) {
       EVT_TRACE(JVMTI_EVENT_VM_START, ("JVMTI Evt VM start event sent" ));
 
       JavaThread *thread  = JavaThread::current();
@@ -544,6 +603,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->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->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
@@ -591,6 +665,9 @@
   }
 
   void post_to_env(JvmtiEnv* env, bool caching_needed) {
+    if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+      return;
+    }
     unsigned char *new_data = NULL;
     jint new_len = 0;
 //    EVT_TRACE(JVMTI_EVENT_CLASS_FILE_LOAD_HOOK,
@@ -602,11 +679,9 @@
                                     _h_protection_domain,
                                     _h_class_being_redefined);
     JvmtiJavaThreadEventTransition jet(_thread);
-    JNIEnv* jni_env =  (JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL)?
-                                                        NULL : jem.jni_env();
     jvmtiEventClassFileLoadHook callback = env->callbacks()->ClassFileLoadHook;
     if (callback != NULL) {
-      (*callback)(env->jvmti_external(), jni_env,
+      (*callback)(env->jvmti_external(), jem.jni_env(),
                   jem.class_being_redefined(),
                   jem.jloader(), jem.class_name(),
                   jem.protection_domain(),
@@ -668,6 +743,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,
@@ -756,6 +835,9 @@
 
 void JvmtiExport::post_compiled_method_unload(
        jmethodID method, const void *code_begin) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   JavaThread* thread = JavaThread::current();
   EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
                  ("JVMTI [%s] method compile unload event triggered",
@@ -765,7 +847,9 @@
   JvmtiEnvIterator it;
   for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
     if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
-
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
                 ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
                  JvmtiTrace::safe_get_thread_name(thread), p2i(method)));
@@ -838,6 +922,8 @@
 bool              JvmtiExport::_can_pop_frame                             = false;
 bool              JvmtiExport::_can_force_early_return                    = false;
 
+bool              JvmtiExport::_early_vmstart_recorded                    = false;
+
 bool              JvmtiExport::_should_post_single_step                   = false;
 bool              JvmtiExport::_should_post_field_access                  = false;
 bool              JvmtiExport::_should_post_field_modification            = false;
@@ -912,6 +998,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);
 
@@ -924,11 +1013,13 @@
   JvmtiEnvThreadStateIterator it(state);
   for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
     if (ets->is_enabled(JVMTI_EVENT_CLASS_LOAD)) {
+      JvmtiEnv *env = ets->get_env();
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_CLASS_LOAD, ("JVMTI [%s] Evt Class Load sent %s",
                                          JvmtiTrace::safe_get_thread_name(thread),
                                          kh()==NULL? "NULL" : kh()->external_name() ));
-
-      JvmtiEnv *env = ets->get_env();
       JvmtiClassEventMark jem(thread, kh());
       JvmtiJavaThreadEventTransition jet(thread);
       jvmtiEventClassLoad callback = env->callbacks()->ClassLoad;
@@ -941,6 +1032,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);
 
@@ -953,11 +1047,13 @@
   JvmtiEnvThreadStateIterator it(state);
   for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
     if (ets->is_enabled(JVMTI_EVENT_CLASS_PREPARE)) {
+      JvmtiEnv *env = ets->get_env();
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_CLASS_PREPARE, ("JVMTI [%s] Evt Class Prepare sent %s",
                                             JvmtiTrace::safe_get_thread_name(thread),
                                             kh()==NULL? "NULL" : kh()->external_name() ));
-
-      JvmtiEnv *env = ets->get_env();
       JvmtiClassEventMark jem(thread, kh());
       JvmtiJavaThreadEventTransition jet(thread);
       jvmtiEventClassPrepare callback = env->callbacks()->ClassPrepare;
@@ -969,6 +1065,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);
@@ -983,6 +1082,9 @@
 
     JvmtiEnvIterator it;
     for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       if (env->is_enabled((jvmtiEvent)EXT_EVENT_CLASS_UNLOAD)) {
         EVT_TRACE(EXT_EVENT_CLASS_UNLOAD, ("JVMTI [?] Evt Class Unload sent %s",
                   kh()==NULL? "NULL" : kh()->external_name() ));
@@ -1018,6 +1120,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",
@@ -1031,6 +1136,9 @@
       !thread->is_hidden_from_external_view()) {
     JvmtiEnvIterator it;
     for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       if (env->is_enabled(JVMTI_EVENT_THREAD_START)) {
         EVT_TRACE(JVMTI_EVENT_THREAD_START, ("JVMTI [%s] Evt Thread Start event sent",
                      JvmtiTrace::safe_get_thread_name(thread) ));
@@ -1048,6 +1156,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)));
 
@@ -1063,10 +1174,13 @@
     JvmtiEnvThreadStateIterator it(state);
     for (JvmtiEnvThreadState* ets = it.first(); ets != NULL; ets = it.next(ets)) {
       if (ets->is_enabled(JVMTI_EVENT_THREAD_END)) {
+        JvmtiEnv *env = ets->get_env();
+        if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+          continue;
+        }
         EVT_TRACE(JVMTI_EVENT_THREAD_END, ("JVMTI [%s] Evt Thread End event sent",
                      JvmtiTrace::safe_get_thread_name(thread) ));
 
-        JvmtiEnv *env = ets->get_env();
         JvmtiThreadEventMark jem(thread);
         JvmtiJavaThreadEventTransition jet(thread);
         jvmtiEventThreadEnd callback = env->callbacks()->ThreadEnd;
@@ -1705,7 +1819,7 @@
 
         JvmtiMethodEventMark jem(thread, mh);
         JvmtiJavaThreadEventTransition jet(thread);
-        JNIEnv* jni_env =  JvmtiEnv::get_phase() == JVMTI_PHASE_PRIMORDIAL? NULL : jem.jni_env();
+        JNIEnv* jni_env = (env->phase() == JVMTI_PHASE_PRIMORDIAL) ? NULL : jem.jni_env();
         jvmtiEventNativeMethodBind callback = env->callbacks()->NativeMethodBind;
         if (callback != NULL) {
           (*callback)(env->jvmti_external(), jni_env, jem.jni_thread(),
@@ -1758,6 +1872,9 @@
 }
 
 void JvmtiExport::post_compiled_method_load(nmethod *nm) {
+  if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   JavaThread* thread = JavaThread::current();
 
   EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
@@ -1767,7 +1884,9 @@
   JvmtiEnvIterator it;
   for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
     if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_LOAD)) {
-
+      if (env->phase() == JVMTI_PHASE_PRIMORDIAL) {
+        continue;
+      }
       EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
                 ("JVMTI [%s] class compile method load event sent %s.%s  ",
                 JvmtiTrace::safe_get_thread_name(thread),
@@ -1797,6 +1916,9 @@
                                             const void *code_begin, const jint map_length,
                                             const jvmtiAddrLocationMap* map)
 {
+  if (env->phase() <= JVMTI_PHASE_PRIMORDIAL) {
+    return;
+  }
   JavaThread* thread = JavaThread::current();
   EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
                  ("JVMTI [%s] method compile load event triggered (by GenerateEvents)",
--- a/src/share/vm/prims/jvmtiExport.hpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiExport.hpp	Thu Mar 17 19:04:01 2016 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -91,6 +91,8 @@
   JVMTI_SUPPORT_FLAG(can_pop_frame)
   JVMTI_SUPPORT_FLAG(can_force_early_return)
 
+  JVMTI_SUPPORT_FLAG(early_vmstart_recorded)
+
   friend class JvmtiEventControllerPrivate;  // should only modify these flags
   JVMTI_SUPPORT_FLAG(should_post_single_step)
   JVMTI_SUPPORT_FLAG(should_post_field_access)
@@ -213,6 +215,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;
@@ -221,6 +225,7 @@
   static void enter_primordial_phase() NOT_JVMTI_RETURN;
 
   // let JVMTI know that the VM isn't up yet but JNI is live
+  static void enter_early_start_phase() NOT_JVMTI_RETURN;
   static void enter_start_phase() NOT_JVMTI_RETURN;
 
   // let JVMTI know that the VM is fully up and running now
@@ -270,6 +275,7 @@
   static bool hide_single_stepping(JavaThread *thread) NOT_JVMTI_RETURN_(false);
 
   // Methods that notify the debugger that something interesting has happened in the VM.
+  static void post_early_vm_start        () NOT_JVMTI_RETURN;
   static void post_vm_start              () NOT_JVMTI_RETURN;
   static void post_vm_initialized        () NOT_JVMTI_RETURN;
   static void post_vm_death              () NOT_JVMTI_RETURN;
--- a/src/share/vm/prims/jvmtiH.xsl	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiH.xsl	Thu Mar 17 19:04:01 2016 +0000
@@ -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"/>
@@ -137,21 +138,21 @@
   <xsl:text> */
 };
 
-JNIEXPORT jint JNICALL 
+JNIEXPORT jint JNICALL
 Agent_OnLoad(JavaVM *vm, char *options, void *reserved);
 
 JNIEXPORT jint JNICALL
 Agent_OnAttach(JavaVM* vm, char* options, void* reserved);
 
-JNIEXPORT void JNICALL 
+JNIEXPORT void JNICALL
 Agent_OnUnload(JavaVM *vm);
 
     /* Forward declaration of the environment */
-        
+
 struct _jvmtiEnv;
 
 struct jvmtiInterface_1_;
-  
+
 #ifdef __cplusplus
 typedef _jvmtiEnv jvmtiEnv;
 #else
@@ -169,7 +170,6 @@
 #endif /* __cplusplus */
 
 #endif /* !_JAVA_JVMTI_H_ */
-
 </xsl:text>
 </xsl:template>
 
@@ -238,7 +238,7 @@
     (jvmtiEnv *jvmti_env</xsl:text>
   <xsl:apply-templates select="parameters" mode="signature">
     <xsl:with-param name="comma">
-      <xsl:text>, 
+      <xsl:text>,
      </xsl:text>
     </xsl:with-param>
    </xsl:apply-templates>
@@ -250,7 +250,7 @@
    <xsl:text>
 
     /* Function Interface */
-    
+
 typedef struct jvmtiInterface_1_ {
 
 </xsl:text>
@@ -290,7 +290,7 @@
       <xsl:text>) (jvmtiEnv* env</xsl:text>
       <xsl:apply-templates select="$thisFunction/parameters" mode="signature">
         <xsl:with-param name="comma">
-          <xsl:text>, 
+          <xsl:text>,
     </xsl:text>
         </xsl:with-param>
       </xsl:apply-templates>
@@ -365,7 +365,7 @@
 
     /* </xsl:text>
     <xsl:value-of select="@label"/>
-    <xsl:text> */ 
+    <xsl:text> */
 </xsl:text>
     <xsl:choose>
       <xsl:when test="@kind='enum'">
--- a/src/share/vm/prims/jvmtiLib.xsl	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiLib.xsl	Thu Mar 17 19:04:01 2016 +0000
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
 
- Copyright (c) 2002, 2012, 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
@@ -44,20 +44,20 @@
   </xsl:template>
 
   <xsl:template name="copyrightComment">
-    <xsl:text>/* </xsl:text>
+    <xsl:text>/*</xsl:text>
     <!-- Copy the Copyright comment from jvmti.xml -->
     <xsl:value-of select="/comment()[position()=1]"/>
-    <xsl:text> */ &#xA;&#xA;</xsl:text>
+    <xsl:text> */&#xA;&#xA;</xsl:text>
   </xsl:template>
 
   <xsl:template name="includeHeader">
     <xsl:call-template name="copyrightComment"/>
-    <xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */ &#xA;</xsl:text>    
+    <xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */&#xA;</xsl:text>    
   </xsl:template>
 
   <xsl:template name="sourceHeader">
     <xsl:call-template name="copyrightComment"/>
-    <xsl:text> // AUTOMATICALLY GENERATED FILE - DO NOT EDIT &#xA;</xsl:text>    
+    <xsl:text> // AUTOMATICALLY GENERATED FILE - DO NOT EDIT&#xA;</xsl:text>    
   </xsl:template>
 
 
--- a/src/share/vm/prims/jvmtiManageCapabilities.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/jvmtiManageCapabilities.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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
@@ -133,9 +133,7 @@
   jc.can_get_owned_monitor_info = 1;
   jc.can_get_owned_monitor_stack_depth_info = 1;
   jc.can_get_current_contended_monitor = 1;
-  // jc.can_get_monitor_info = 1;
-  jc.can_tag_objects = 1;                 // TODO: this should have been removed
-  jc.can_generate_object_free_events = 1; // TODO: this should have been removed
+  jc.can_generate_early_vmstart = 1;
   return jc;
 }
 
@@ -454,6 +452,8 @@
     tty->print_cr("can_generate_resource_exhaustion_heap_events");
   if (cap->can_generate_resource_exhaustion_threads_events)
     tty->print_cr("can_generate_resource_exhaustion_threads_events");
+  if (cap->can_generate_early_vmstart)
+    tty->print_cr("can_generate_early_vmstart");
 }
 
 #endif
--- a/src/share/vm/prims/methodHandles.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/methodHandles.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -1177,9 +1177,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/nativeLookup.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/nativeLookup.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -41,7 +41,9 @@
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
 #include "utilities/macros.hpp"
-
+#if INCLUDE_TRACE
+#include "trace/traceMacros.hpp"
+#endif
 
 static void mangle_name_on(outputStream* st, Symbol* name, int begin, int end) {
   char* bytes = (char*)name->bytes() + begin;
@@ -131,6 +133,9 @@
   { CC"Java_jdk_vm_ci_runtime_JVMCI_initializeRuntime",            NULL, FN_PTR(JVM_GetJVMCIRuntime)             },
   { CC"Java_jdk_vm_ci_hotspot_CompilerToVM_registerNatives",       NULL, FN_PTR(JVM_RegisterJVMCINatives)        },
 #endif
+#if INCLUDE_TRACE
+  { CC"Java_jdk_jfr_internal_JVM_registerNatives",                 NULL, TRACE_REGISTER_NATIVES                  },
+#endif
 };
 
 static address lookup_special_native(char* jni_name) {
--- a/src/share/vm/prims/whitebox.cpp	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/prims/whitebox.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -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"
@@ -1250,6 +1251,43 @@
   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(module, version, location, packages, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExports(JNIEnv* env, jobject o, jobject from_module, jstring package, jobject to_module))
+  Modules::add_module_exports_qualified(from_module, package, to_module, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExportsToAllUnnamed(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_exports_to_all_unnamed(module, package, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddModuleExportsToAll(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_exports(module, package, NULL, CHECK);
+WB_END
+
+WB_ENTRY(void, WB_AddReadsModule(JNIEnv* env, jobject o, jobject from_module, jobject source_module))
+  Modules::add_reads_module(from_module, source_module, CHECK);
+WB_END
+
+WB_ENTRY(jboolean, WB_CanReadModule(JNIEnv* env, jobject o, jobject asking_module, jobject source_module))
+  return Modules::can_read_module(asking_module, source_module, THREAD);
+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(from_module, package, to_module, THREAD);
+WB_END
+
+WB_ENTRY(void, WB_AddModulePackage(JNIEnv* env, jobject o, jclass module, jstring package))
+  Modules::add_module_package(module, package, CHECK);
+WB_END
+
+WB_ENTRY(jobject, WB_GetModuleByPackageName(JNIEnv* env, jobject o, jobject loader, jstring package))
+  return Modules::get_module_by_package_name(loader, package, THREAD);
+WB_END
+
 WB_ENTRY(jlong, WB_IncMetaspaceCapacityUntilGC(JNIEnv* env, jobject wb, jlong inc))
   if (inc < 0) {
     THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
@@ -1278,7 +1316,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 :
@@ -1287,10 +1324,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();
@@ -1417,6 +1450,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
@@ -1528,10 +1565,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  },
@@ -1649,6 +1685,24 @@
   {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"GetModuleByPackageName", CC"(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;",
+                                                      (void*)&WB_GetModuleByPackageName },
+  {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     },
@@ -1675,6 +1729,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	Tue Mar 15 13:48:21 2016 -0700
+++ b/src/share/vm/runtime/arguments.cpp	Thu Mar 17 19:04:01 2016 +0000
@@ -94,6 +94,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,7 +120,9 @@
 SystemProperty *Arguments::_java_library_path = NULL;
 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;
+
+PathString *Arguments::_system_boot_class_path = NULL;
 
 char* Arguments::_ext_dirs = NULL;
 
@@ -195,6 +200,12 @@
 
 // Initialize system properties key and value.
 void Arguments::init_system_properties() {
+
+  // Set up _system_boot_class_path which is not a property but
+  // relies heavily on argument processing and the jdk.boot.class.path.append
+  // property. It is used to store the underlying system boot class path.
+  _system_boot_class_path = new PathString(NULL);
+
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.specification.name",
                                                                  "Java Virtual Machine Specification",  false));
   PropertyList_add(&_system_properties, new SystemProperty("java.vm.version", VM_Version::vm_release(),  false));
@@ -208,16 +219,19 @@
   _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);
-  _sun_boot_class_path = new SystemProperty("sun.boot.class.path", NULL,  true);
-
   _java_class_path = new SystemProperty("java.class.path", "",  true);
+  // jdk.boot.class.path.append is a non-writeable, internal property.
+  // It can only be set by either:
+  //    - -Xbootclasspath/a:
+  //    - AddToBootstrapClassLoaderSearch during JVMTI OnLoad phase
+  _jdk_boot_class_path_append = new SystemProperty("jdk.boot.class.path.append", "", false, true);
 
   // Add to System Property list.
   PropertyList_add(&_system_properties, _sun_boot_library_path);
   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();
@@ -542,19 +556,19 @@
 }
 #endif
 
-// Constructs the system class path (aka boot class path) from the following
-// components, in order:
+// Constructs the system 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
-// complete.
-class SysClassPath: public StackObj {
+// complete. After argument processing, the combined components are copied
+// to Arguments::_system_boot_class_path via a call to Arguments::set_sysclasspath.
+class ArgumentBootClassPath: public StackObj {
 public:
-  SysClassPath(const char* base);
-  ~SysClassPath();
+  ArgumentBootClassPath(const char* base);
+  ~ArgumentBootClassPath();
 
   inline void set_base(const char* base);
   inline void add_prefix(const char* prefix);
@@ -562,9 +576,9 @@
   inline void add_suffix(const char* suffix);
   inline void reset_path(const char* base);
 
-  inline const char* get_base()     const { return _items[_scp_base]; }
-  inline const char* get_prefix()   const { return _items[_scp_prefix]; }
-  inline const char* get_suffix()   const { return _items[_scp_suffix]; }
+  inline const char* get_base()     const { return _items[_bcp_base]; }
+  inline const char* get_prefix()   const { return _items[_bcp_prefix]; }
+  inline const char* get_suffix()   const { return _items[_bcp_suffix]; }
 
   // Combine all the components into a single c-heap-allocated string; caller
   // must free the string if/when no longer needed.
@@ -580,55 +594,55 @@
   // 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_base,          // the default sysclasspath
-    _scp_suffix,        // from -Xbootclasspath/a:...
-    _scp_nitems         // the number of items, must be last.
+    _bcp_prefix,        // was -Xpatch:...
+    _bcp_base,          // the default system boot class path
+    _bcp_suffix,        // from -Xbootclasspath/a:...
+    _bcp_nitems         // the number of items, must be last.
   };
 
-  const char* _items[_scp_nitems];
+  const char* _items[_bcp_nitems];
 };
 
-SysClassPath::SysClassPath(const char* base) {
+ArgumentBootClassPath::ArgumentBootClassPath(const char* base) {
   memset(_items, 0, sizeof(_items));
-  _items[_scp_base] = base;
+  _items[_bcp_base] = base;
 }
 
-SysClassPath::~SysClassPath() {
+ArgumentBootClassPath::~ArgumentBootClassPath() {
   // Free everything except the base.
-  for (int i = 0; i < _scp_nitems; ++i) {
-    if (i != _scp_base) reset_item_at(i);
+  for (int i = 0; i < _bcp_nitems; ++i) {
+    if (i != _bcp_base) reset_item_at(i);
   }
 }
 
-inline void SysClassPath::set_base(const char* base) {
-  _items[_scp_base] = base;
+inline void ArgumentBootClassPath::set_base(const char* base) {
+  _items[_bcp_base] = base;
 }
 
-inline void SysClassPath::add_prefix(const char* prefix) {
-  _items[_scp_prefix] = add_to_path(_items[_scp_prefix], prefix, true);
+inline void ArgumentBootClassPath::add_prefix(const char* prefix) {
+  _items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], prefix, true);
 }
 
-inline void SysClassPath::add_suffix_to_prefix(const char* suffix) {
-  _items[_scp_prefix] = add_to_path(_items[_scp_prefix], suffix, false);
+inline void ArgumentBootClassPath::add_suffix_to_prefix(const char* suffix) {
+  _items[_bcp_prefix] = add_to_path(_items[_bcp_prefix], suffix, false);
 }
 
-inline void SysClassPath::add_suffix(const char* suffix) {
-  _items[_scp_suffix] = add_to_path(_items[_scp_suffix], suffix, false);
+inline void ArgumentBootClassPath::add_suffix(const char* suffix) {
+  _items[_bcp_suffix] = add_to_path(_items[_bcp_suffix], suffix, false);
 }
 
-inline void SysClassPath::reset_item_at(int index) {
-  assert(index < _scp_nitems && index != _scp_base, "just checking");
+inline void ArgumentBootClassPath::reset_item_at(int index) {
+  assert(index < _bcp_nitems && index != _bcp_base, "just checking");
   if (_items[index] != NULL) {
     FREE_C_HEAP_ARRAY(char, _items[index]);
     _items[index] = NULL;
   }
 }
 
-inline void SysClassPath::reset_path(const char* base) {
+inline void ArgumentBootClassPath::reset_path(const char* base) {
   // Clear the prefix and suffix.
-  reset_item_at(_scp_prefix);
-  reset_item_at(_scp_suffix);
+  reset_item_at(_bcp_prefix);
+  reset_item_at(_bcp_suffix);
   set_base(base);
 }
 
@@ -637,17 +651,21 @@
 
 // Combine the bootclasspath elements, some of which may be null, into a single
 // c-heap-allocated string.
-char* SysClassPath::combined_path() {
-  assert(_items[_scp_base] != NULL, "empty default sysclasspath");
-
-  size_t lengths[_scp_nitems];
+char* ArgumentBootClassPath::combined_path() {
+  assert(_items[_bcp_base] != NULL, "empty default sysclasspath");
+
+  size_t lengths[_bcp_nitems];
   size_t total_len = 0;
 
   const char separator = *os::path_separator();
 
   // Get the lengths.
   int i;
-  for (i = 0; i < _scp_nitems; ++i) {
+  for (i = 0; i < _bcp_nitems; ++i) {
+    if (i == _bcp_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).
@@ -659,7 +677,7 @@
   // Copy the _items to a single string.
   char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal);
   char* cp_tmp = cp;
-  for (i = 0; i < _scp_nitems; ++i) {
+  for (i = 0; i < _bcp_nitems; ++i) {
     if (_items[i] != NULL) {
       memcpy(cp_tmp, _items[i], lengths[i]);
       cp_tmp += lengths[i];
@@ -672,7 +690,7 @@
 
 // Note:  path must be c-heap-allocated (or NULL); it is freed if non-null.
 char*
-SysClassPath::add_to_path(const char* path, const char* str, bool prepend) {
+ArgumentBootClassPath::add_to_path(const char* path, const char* str, bool prepend) {
   char *cp;
 
   assert(str != NULL, "just checking");
@@ -706,7 +724,7 @@
 
 // Scan the directory and append any jar or zip files found to path.
 // Note:  path must be c-heap-allocated (or NULL); it is freed if non-null.
-char* SysClassPath::add_jars_to_path(char* path, const char* directory) {
+char* ArgumentBootClassPath::add_jars_to_path(char* path, const char* directory) {
   DIR* dir = os::opendir(directory);
   if (dir == NULL) return path;
 
@@ -1375,6 +1393,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
 
@@ -2553,8 +2619,8 @@
                                    const JavaVMInitArgs *java_options_args,
                                    const JavaVMInitArgs *cmd_line_args) {
   // For components of the system classpath.
-  SysClassPath scp(Arguments::get_sysclasspath());
-  bool scp_assembly_required = false;
+  ArgumentBootClassPath bcp(Arguments::get_sysclasspath());
+  bool bcp_assembly_required = false;
 
   // Save default settings for some mode flags
   Arguments::_AlwaysCompileLoopMethods = AlwaysCompileLoopMethods;
@@ -2572,13 +2638,13 @@
   // Parse args structure generated from JAVA_TOOL_OPTIONS environment
   // variable (if present).
   jint result = parse_each_vm_init_arg(
-      java_tool_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR);
+      java_tool_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
   if (result != JNI_OK) {
     return result;
   }
 
   // Parse args structure generated from the command line flags.
-  result = parse_each_vm_init_arg(cmd_line_args, &scp, &scp_assembly_required,
+  result = parse_each_vm_init_arg(cmd_line_args, &bcp, &bcp_assembly_required,
                                   Flag::COMMAND_LINE);
   if (result != JNI_OK) {
     return result;
@@ -2587,13 +2653,13 @@
   // Parse args structure generated from the _JAVA_OPTIONS environment
   // variable (if present) (mimics classic VM)
   result = parse_each_vm_init_arg(
-      java_options_args, &scp, &scp_assembly_required, Flag::ENVIRON_VAR);
+      java_options_args, &bcp, &bcp_assembly_required, Flag::ENVIRON_VAR);
   if (result != JNI_OK) {
     return result;
   }
 
   // Do final processing now that all arguments have been parsed
-  result = finalize_vm_init_args(&scp, scp_assembly_required);
+  result = finalize_vm_init_args(&bcp, bcp_assembly_required);
   if (result != JNI_OK) {
     return result;
   }
@@ -2647,8 +2713,8 @@
 }
 
 jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
-                                       SysClassPath* scp_p,
-                                       bool* scp_assembly_required_p,
+                                       ArgumentBootClassPath* bcp_p,
+                                       bool* bcp_assembly_required_p,
                                        Flag::Flags origin) {
   // For match_option to return remaining or value part of option string
   const char* tail;
@@ -2700,16 +2766,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;
+      bcp_p->add_suffix(tail);
+      *bcp_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) {
@@ -2761,9 +2829,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
@@ -3029,12 +3102,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.0=", &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)) {
+                bcp_p->add_prefix(dir);
+                *bcp_assembly_required_p = true;
+              }
+              FREE_C_HEAP_ARRAY(char, dir);
+            }
+          }
+        }
+      }
     // -Xint
     } else if (match_option(option, "-Xint")) {
           set_mode_flags(_int);
@@ -3294,6 +3405,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
@@ -3329,7 +3452,7 @@
       // Keep replacing ";;" -> ";" until we have no more ";;" (windows)
     }
 
-    _java_class_path->set_value(copy);
+    _java_class_path->set_writeable_value(copy);
     FreeHeap(copy); // a copy was made by set_value, so don't need this anymore
   }
 }
@@ -3380,7 +3503,7 @@
   return nonEmptyDirs;
 }
 
-jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) {
+jint Arguments::finalize_vm_init_args(ArgumentBootClassPath* bcp_p, bool bcp_assembly_required) {
   // check if the default lib/endorsed directory exists; if so, error
   char path[JVM_MAXPATHLEN];
   const char* fileSep = os::file_separator();
@@ -3416,11 +3539,16 @@
     return JNI_ERR;
   }
 
-  if (scp_assembly_required) {
+  if (bcp_assembly_required) {
     // Assemble the bootclasspath elements into the final path.
-    char *combined_path = scp_p->combined_path();
+    char *combined_path = bcp_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.
@@ -3766,6 +3894,11 @@
 
 void Arguments::set_shared_spaces_flags() {
   if (DumpSharedSpaces) {